Java网络编程之TCP
Java网络编程之TCP
TCP主要需要两个类:Socket和ServerSocket,Socket是客户端连接服务器时创建,参数需要指定服务器的ip和端口,ServerSocket是服务器端创建,参数指定端口,如下:
Socket socket = new Socket("localhost",8888);//Client.java客户端
ServerSocket serverSocket = new ServerSocket(8888);//Server.java服务器端
//服务器ip为本机,端口为8888
我的想法:要实现单聊和群聊,首先,我得为标识每个客户端,我选择姓名,这样每个用户都知道是谁发的消息,那么,我需要每个姓名对应一个客户端Socket,用map存储
废话不多说,直接上代码:
1. 客户端:
```java
public class TcpClient {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入用户名》》");
String userName = scanner.next();
Socket socket = new Socket("localhost",8888);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeUTF(userName);
new Thread(new SendMsg(socket)).start();
new Thread(new ReceiveMsg(socket)).start();
}
}
```
2. 客户端发送消息线程:
public class SendMsg implements Runnable{
private Socket socket;
public SendMsg(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
while(true) {
BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));
String[] msg = buffer.readLine().split("@");
MessageBean messageBean = new MessageBean(msg[0],msg[1]);
// DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// out.writeUTF(msg);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(messageBean);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3. 客户端接收消息线程:
public class ReceiveMsg implements Runnable{
private Socket socket;
public ReceiveMsg(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
while(true) {
DataInputStream in = new DataInputStream(socket.getInputStream());
System.out.println(in.readUTF());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
4. 服务器端:
public class TcpServer {
public static void main(String[] args) throws Exception {
try {
//List<Socket> sockets = new ArrayList<>();
Map<String,Socket> map = new HashMap<>();
ServerSocket serverSocket = new ServerSocket(8888);
while(true) {
Socket socket = serverSocket.accept();
//服务器第一次接收到的信息一定是用户名
DataInputStream in = new DataInputStream(socket.getInputStream());
String username = in.readUTF();
synchronized (map) {
map.put(username, socket);
}
//能够保证在同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果
// synchronized (sockets) {
// sockets.add(socket);
// }
new Thread(new ServerHandler(socket,map)).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
5. 服务器处理事务线程端:
public class ServerHandler implements Runnable {
private Socket socket;
private Map<String, Socket> map;
public ServerHandler(Socket socket,Map<String, Socket> map) {
this.socket = socket;
this.map = map;
}
public String findKey(Map<String, Socket> map,Socket socket) {
Iterator<String> it = map.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
if (map.get(key).equals(socket)) return key;
}
return null;
}
@Override
public void run() {
InetAddress address = socket.getInetAddress();
String ip = address.getHostAddress();
String username = findKey(map, socket);
System.out.println("ip为"+ip+"的"+username+":上线了----");
try {
while(true) {
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
MessageBean messageBean = (MessageBean) in.readObject();
String msg = messageBean.getMsg();
String toPerson = messageBean.getToPerson();
if ("all".equals(toPerson)) {
//群聊
msg = username+":"+msg;
for(String key : map.keySet()){
if (username.equals(key)) {
continue;
}
DataOutputStream out = new DataOutputStream(map.get(key).getOutputStream());
out.writeUTF(msg);
}
}else {
//私聊
if (map.get(toPerson) == null) {
DataOutputStream out = new DataOutputStream(map.get(username).getOutputStream());
out.writeUTF("抱歉,"+toPerson+"不在线。。。。");
}else {
msg = username+"对您私聊说:"+msg;
DataOutputStream out = new DataOutputStream(map.get(toPerson).getOutputStream());
out.writeUTF(msg);
}
}
}
} catch (Exception e) {
//e.printStackTrace();
System.out.println(username+"下线了。。。。。");
synchronized (map) {
map.remove(username, socket);
}
}
}
}
6. 消息体类:
public class MessageBean implements Serializable{
private String msg;
private String toPerson;
public MessageBean() {
}
public MessageBean(String msg,String toPerson) {
this.msg = msg;
this.toPerson = toPerson;
}
public String getMsg() {
return msg;
}
public String getToPerson() {
return toPerson;
}
public void setMsg(String msg) {
this.msg = msg;
}
public void setToPerson(String toPerson) {
this.toPerson = toPerson;
}
}
运行结果:


Java网络编程之TCP的更多相关文章
- Java网络编程之TCP、UDP
Java网络编程之TCP.UDP 2014-11-25 15:23 513人阅读 评论(0) 收藏 举报 分类: java基础及多线程(28) 版权声明:本文为博主原创文章,未经博主允许不得转载. ...
- java网络编程之TCP通讯
java中的网络编程之TCP协议的详细介绍,以及如何使用,同时我在下面举2例说明如何搭配IO流进行操作, /* *TCP *建立连接,形成传输数据的通道: *在连接中进行大数据量传输: *通过三次握手 ...
- Java网络编程之TCP通信
一.概述 Socket类是Java执行客户端TCP操作的基础类,这个类本身使用代码通过主机操作系统的本地TCP栈进行通信.Socket类的方法会建立和销毁连接,设置各种Socket选项. Server ...
- java 网络编程之TCP通信和简单的文件上传功能
*/ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...
- 4.Java网络编程之TCP/UDP
常见传输协议: UDP , TCP UDP协议: 特点: 1.将数据及源和目的封装成数据包中,不需要建立连接 2.每个数据包的大小限制在64K内 ...
- java网络编程之TCP实例
Dgram类 package Socket; import java.net.DatagramPacket; import java.net.InetAddress; public class Dgr ...
- 网络编程之TCP编程
网络编程之TCP编程 前面已经介绍过关于TCP协议的东西,这里不做赘述.Java对于基于TCP协议的网络通信提供了良好的封装,Java使用socket对象来代表两端的通信窗口,并通过Socket产生I ...
- Java网络编程之InetAddress浅析
Java网络编程之InetAddress浅析 一.InetAddress综述 IP地址是IP使用的32位(IPv4)或者128位(IPv6)位无符号数字,它是传输层协议TCP,UDP的基础.InetA ...
- Python网络编程之TCP套接字简单用法示例
Python网络编程之TCP套接字简单用法示例 本文实例讲述了Python网络编程之TCP套接字简单用法.分享给大家供大家参考,具体如下: 上学期学的计算机网络,因为之前还未学习python,而jav ...
随机推荐
- 7.27考试总结(NOIP模拟25)[random·string·queue]
死亡的尽头,没有神 T1 random 解题思路 这波是找规律完胜了.. lby dalao根据样例找出了正确的式子:\(\dfrac{n^2-1}{9}\) 然而,我这个菜鸡却推出了这样一个错误的式 ...
- NetCoreMvc系列文章02---依赖注入
.netCore自带依赖注入,支持构造函数注入,如不了解IOC 和DI 思想的请看我其它文章中关于这主面的介绍.如Startup.cs类中的Configure方法其中IApplicationBuild ...
- charles f配置sslproxy 对protobuf 接口抓包 -不推荐
charles 配置sslproxy help-安装电脑证书 手机连接访问电脑,下载允许手机 手机连接vpn 手机访问chls.pro/ssl -下载证书 request可以看到protobuf_tx ...
- solr(CVE-2017-12629)远程命令执行
影响版本Apache Solr 5.5.0到7.0.1版本 solr(CVE-2017-12629-RCE) 环境搭建 1.burp检测 创建listen POST /solr/demo/config ...
- time() 在thinkphp 3.2.3 模板格式化输出
{$ltime|date="Y-m-d",###}
- 论文笔记:(TOG2019)DGCNN : Dynamic Graph CNN for Learning on Point Clouds
目录 摘要 一.引言 二.相关工作 三.我们的方法 3.1 边缘卷积Edge Convolution 3.2动态图更新 3.3 性质 3.4 与现有方法比较 四.评估 4.1 分类 4.2 模型复杂度 ...
- 承载童年的游戏机,已停产!但我在 GitHub 找到了它们
那些年,上网用的是电话线,小企鹅也只会笨拙地左右摇晃,手机还只是打电话的工具.虽然那些年没有互联网,但游戏机承载了我的童年. 小时候我老是追着我的两个哥哥,他们带我玩了好多种游戏机,比如街机.红白机. ...
- DNS服务器(一)正向解析
一.DNS简介 在日常生活中人们习惯便用域名访问服务器,但机器间互相只认IP地址,域名与1P地址之间是多对一的关系,一个ip地址不一定只对应一个域名,且一个域名只可以对应一个ip地址,它们之间的转换工 ...
- 串、KMP模式匹配算法
串是由0个或者多个字符组成的有限序列,又名叫字符串. 串的比较: 串的比较是通过组成串的字符之间的编码来进行的,而字符的编码指的是字符在对应字符集中的序号. 计算机中常用的ASCII编码,由8位二进制 ...
- HCIA-网络层IP地址
TCP/IP 每一层关联性 网络接口层-->TYPE 上层的网络层 --> Protocol -->不同的传输层协议 DSAP SSAP IP地址 剩下的8个字节 IPV4地址 4个 ...