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 ...
随机推荐
- js之 foreach, map, every, some
js中array有四个方法 foreach, map, every, some,其使用各有倾向. 关注点一:foreach 和 map 无法跳出循环,每个元素均执行 foreach 和 map 无法跳 ...
- Html模板引擎Handlerbars使用demo
1.自定义demo <html> <head> <script src="./handlebars-v4.0.12.js"></scrip ...
- odoo12里面的RPC【远程过程调用】
odoo的RPC有两种:RPC API:1.xml-rpc 2.json-rpc 案例 x ...
- Java 正则表达式 简单用法
正则表达式的具体写法网上有很多了,这里只记录在 Java 中怎么使用. java.util.regex.Matcher.java.util.regex.Pattern 主要有: String.matc ...
- 一键设置WPS_Office_2019专业版的定时自动备份的批处理文件
一键设置WPS_Office_2019专业版的定时自动备份的批处理文件 rem ================================================ rem 一键设置WPS ...
- BSTestRunner增加历史执行记录展示和重试功能
之前对于用例的失败重试,和用例的历史测试记录存储展示做了很多的描述呢,但是都是基于各个项目呢,不方便使用,为了更好的使用,我们对这里进行抽离,抽离出来一个单独的模块,集成到BSTestRunner中, ...
- openssl查看证书命令
openssl x509部分命令打印出证书的内容:openssl x509 -in cert.pem -noout -text打印出证书的系列号openssl x509 -in cert.pem -n ...
- Java 7 新特性之try-with-resources实践理解
想象这么一个情景,我们需要使用一个资源,在使用完之后需要关闭该资源,并且使用该资源的过程中有可能有异常抛出.此时我们都会想到用try-catch语句,在finally中关闭该资源.此时会有一个问题,如 ...
- web笔记随笔
1.Web服务组件 8.第三方内容:广告统计.mockup 7.Web前端框架: HTML5. jQuery. Bootstrap 6.Web应用: CMS. BBS. Blog 5.Web开发框架: ...
- Java面向对象14——接口
接口 package oop.demon01.demon09; //抽象思维~Java //interface 定义的关键字 , 接口都需要有实现类 public interface Use ...