# chatProject **Repository Path**: maxuxu2000/chatProject ## Basic Information - **Project Name**: chatProject - **Description**: java网络编程,通过tcp/udp实现聊天功能 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-03-18 - **Last Updated**: 2024-10-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # java网络编程 ## 1. 简介 通过tcp,udp搭建简单的聊天平台 ## 2. tcp 方式连接 ### 2.1 创建服务端 ```java public static void main(String[] args) { ServerSocket serverSocket = null; Socket socket = null; InputStream inputStream = null; ByteArrayOutputStream byteArrayOutputStream = null; try { // 1. 服务器设置地址 serverSocket = new ServerSocket(9999); // 2.等待客户端连接 socket = serverSocket.accept(); // 3. 读取客户端的消息 inputStream = socket.getInputStream(); // 管道流 byteArrayOutputStream = new ByteArrayOutputStream(); byte[] bytes = new byte[1024]; int len; while ((len=inputStream.read(bytes))!=-1){ byteArrayOutputStream.write(bytes,0,len); } System.out.println(byteArrayOutputStream.toString()); } catch (IOException e) { e.printStackTrace(); }finally { if (byteArrayOutputStream!=null){ try { byteArrayOutputStream.close(); }catch (IOException e){ e.printStackTrace(); } } if (inputStream!=null){ try { inputStream.close(); }catch (IOException e){ e.printStackTrace(); } } if (socket!=null){ try { socket.close(); }catch (IOException e){ e.printStackTrace(); } } if (serverSocket!=null){ try { serverSocket.close(); }catch (IOException e){ e.printStackTrace(); } } } } ``` ### 2.2 tcp 客户端 ```java public static void main(String[] args) { Socket socket = null; OutputStream outputStream = null; try { // 1. 获取服务器端的地址和端口号 InetAddress serverIP = InetAddress.getByName("127.0.0.1"); int port = 9999; // 2. 创建一个socket连接 socket = new Socket(serverIP, port); // 3. 发送消息 io 流 outputStream = socket.getOutputStream(); outputStream.write("hello,welcome".getBytes()); } catch (IOException e) { e.printStackTrace(); }finally { if (outputStream!=null){ try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket!=null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } ``` ## 3. upd 方式连接 ### 3.1 客户端 ```java public static void main(String[] args) throws Exception{ // 1. 建立一个socket DatagramSocket datagramSocket = new DatagramSocket(); // 2. 建个包 String msg = "hello,server"; InetAddress localhost = InetAddress.getByName("localhost"); int port = 9999; // 数据起始,发送目标 DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,port); // 3. 发送包 datagramSocket.send(packet); // 4. 关闭流 datagramSocket.close(); } ``` ### 3.2 服务端 ```java public static void main(String[] args) throws Exception { // 开放端口 DatagramSocket socket = new DatagramSocket(9999); // 接收数据包 byte[] buffer = new byte[1024]; DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length); // 接受阻塞 socket.receive(packet); System.out.println(packet.getAddress().getHostAddress()); System.out.println(new String(packet.getData(),0,packet.getLength())); //关闭连接 socket.close(); } ``` ## 4. 循环输入输出 ### 4.1 发送端 ```java public static void main(String[] args) throws Exception { DatagramSocket socket = new DatagramSocket(8888); // 准备数据:控制台读取 System.in BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); while (true){ String data = reader.readLine(); byte[] datas = data.getBytes(); DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress("localhost", 6666)); socket.send(packet); if (data.equals("bye")){ break; } } socket.close(); } ``` ### 4.2 接收端 ```java public static void main(String[] args) throws Exception { DatagramSocket socket = new DatagramSocket(6666); while (true) { // 准备接受包裹 byte[] buffer = new byte[1024]; DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length); socket.receive(packet); // 阻塞式接受包裹 // 断开连接 byte[] data = packet.getData(); String receiveData = new String(data, 0, data.length); System.out.println(receiveData.trim()); if (receiveData.trim().equals("bye")){ break; } } socket.close(); } ``` > 发送到发送信息,在接收端会打印,输入 “bye” 停止 ## 5. 多线程传输-实例 ### 5.1 创建发送端 ```java public class TalkSend implements Runnable{ DatagramSocket socket = null; BufferedReader reader = null; private String fromIP; private String toIP; private int fromPort; private int toPort; public TalkSend(int fromPort, String toIP, int toPort) { this.fromPort = fromPort; this.toIP = toIP; this.toPort = toPort; try { socket = new DatagramSocket(fromPort); reader = new BufferedReader(new InputStreamReader(System.in)); } catch (SocketException e) { e.printStackTrace(); } } @Override public void run() { while (true){ try { String data = reader.readLine(); byte[] datas = data.getBytes(); DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(this.toIP, this.toPort)); socket.send(packet); if (data.equals("bye")){ break; } }catch (Exception e) { e.printStackTrace(); } } socket.close(); } } ``` ### 5.2 创建接收端 ```java public class TalkReceiver implements Runnable{ DatagramSocket socket = null; private int port; private String msgFrom; public TalkReceiver(int port, String msgFrom) { this.port = port; this.msgFrom = msgFrom; try { socket = new DatagramSocket(port); } catch (SocketException e) { e.printStackTrace(); } } @Override public void run() { while (true) { try { // 准备接受包裹 byte[] buffer = new byte[1024]; DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length); socket.receive(packet); // 阻塞式接受包裹 // 断开连接 byte[] data = packet.getData(); String receiveData = new String(data, 0, data.length); System.out.println(msgFrom+receiveData.trim()); if (receiveData.trim().equals("bye")){ break; } } catch (IOException e) { e.printStackTrace(); } } socket.close(); } } ``` ### 5.3 创建双向线程 例如:老师和学生,两者可以互相聊天,互为接收和发送端,所以写两个线程类,每个类都有双方的线程 **老师端线程** ```java public static void main(String[] args) { new Thread(new TalkSend(5555, "localhost", 8888)).start(); new Thread(new TalkReceiver(9999, "学生:")).start(); } ``` **学生端线程** ```java public static void main(String[] args) { // 开启两个线程 new Thread(new TalkSend(7777,"localhost",9999)).start(); new Thread(new TalkReceiver(8888, "老师:")).start(); } ``` ### 5.4 分别运行老师端和学生端的线程 两个窗口发送消息可以正常接收,输入“bye” 则,己方断开连接,无法再发送消息(但能接收);对方正常发送,如果对方也输入“bye”,那么整个聊天结束,也就是必须双方都发送“bye”才可以停止通信。