TCP Socket编程--聊天雏形
程序员文章站
2024-01-31 16:05:34
...
好久没有写javaeye博客了,最近写了个TCP Socket编程,和大家一起分享!
聊天原理:启动TCP服务端,等待客户端连接,当客户端连接到服务端后,服务端创建一个线程针对该客户端进行读写,服务端继续在指定端口监听客户端连接。客户端连接成功后,创建写线程和读线程,来与服务器端进行通信。服务器端线程接收到客户端的信息,再把该信息转发给消息的目的地客户端。目的地客户端通过发送线程发送消息给服务器端,服务器端接收到消息,再把消息转发给目的地客户端。服务器端线程并不会主动地发送消息给客户端,服务器端线程只是在中转客户端发送过来的信息,把消息发送给指定的目的地客户端而已。
如何实现从客户端A发送消息给客户端B呢?
1、客户端A通过写线程,写入消息到服务器端
2、服务器端接收到客户端A的消息,并解析消息内容,得知消息是要发送给客户端B,服务器端线程写入消息给客户端B
3、客户端B读取线程读取到服务器线程发送来的数据
这样的就完成了从客户端A发送消息到客户端B,通过客户端B也通过同样的方式发送消息给客户端A。完成双向通信。
服务端:
package com.guchao.chat; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class TCPServer { private Map<String, Socket> sockets = new HashMap<String, Socket>(); /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { new TCPServer().go(); } public void go(){ ServerSocket ss = null; try { ss = new ServerSocket(8888); System.out.println("服务器启动成功,在8888端口监听用户连接!"); } catch (IOException e1) { e1.printStackTrace(); } Socket s = null; int i = 0; while(true){ try { s = ss.accept(); String clientName = "Client_"+(++i); sockets.put(clientName, s); sendMessageToOtherClients(clientName); System.out.println(clientName+"连接到服务器!"); } catch (IOException e) { e.printStackTrace(); } ReadAndWriteThread t = new ReadAndWriteThread(s); new Thread(t).start(); } } private void sendMessageToOtherClients(String clientName) { if(sockets != null && sockets.size() > 0){ for (Iterator<String> iterator = sockets.keySet().iterator(); iterator.hasNext();) { String key = (String) iterator.next(); Socket s = sockets.get(key); try { DataOutputStream dos = new DataOutputStream(s.getOutputStream()); dos.writeUTF(clientName+"已经登陆了服务器!"); } catch (IOException e) { e.printStackTrace(); } } } } class ReadAndWriteThread implements Runnable{ private DataInputStream dis = null; public ReadAndWriteThread(Socket s){ try { dis = new DataInputStream(s.getInputStream()); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { String str = ""; while(true){ try { /** * 定义消息格式为hello,jjkdfjaf*客户端名称* * 例如:hello,zhangsan*Client_2* * 表示消息hello,zhangsan发送给Client_2 */ str = dis.readUTF(); if("bye".equals(str)) break; sendMessageToClient(str); } catch (IOException e) { e.printStackTrace(); } } } } private void sendMessageToClient(String str){ int startPosition = str.lastIndexOf("*", str.lastIndexOf("*")-1); int endPosition = str.lastIndexOf("*"); if(startPosition > 0 && endPosition > 0 && endPosition > startPosition){ String clientName = str.substring(startPosition+1, endPosition); Socket s = sockets.get(clientName); DataOutputStream dos = null; try { if(s != null){ dos = new DataOutputStream(s.getOutputStream()); dos.writeUTF(str); } } catch (IOException e) { e.printStackTrace(); } } } }
客户端:
package com.guchao.chat; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import java.net.UnknownHostException; public class TCPClient { public static void main(String[] args) throws UnknownHostException, IOException{ new TCPClient().go(); } public void go() { try { Socket s = new Socket("127.0.0.1",8888); // 启动读线程,从socket中读取信息 RecvThread recv = new RecvThread(s); new Thread(recv).start(); // 启动写线程,写入信息到socket中 SendThread send = new SendThread(s); new Thread(send).start(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } class RecvThread implements Runnable{ private DataInputStream dis = null; public RecvThread(Socket s){ try { dis = new DataInputStream(s.getInputStream()); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { String str = ""; while(true){ try { //从socket中读取信息 str = dis.readUTF(); if("bye".equals(str)) break; System.out.println("received message:"+str); } catch (IOException e) { e.printStackTrace(); } } } } class SendThread implements Runnable{ private DataOutputStream dos; public SendThread(Socket s){ try { dos = new DataOutputStream(s.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { String str = ""; while(true){ System.out.println("input message:"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); try { str = br.readLine(); // 写入信息到socket中 dos.writeUTF(str); if("bye".equals(str)) break; } catch (IOException e) { e.printStackTrace(); } } } } }
上一篇: Http和Socket详解
推荐阅读
-
TCP Socket编程--聊天雏形
-
从零探索Java网络编程01之 TCP/IP 与 Socket
-
[JAVA网络编程]用Socket与网络调试助手(NetAssist)进行TCP通讯过程中遇到的问题
-
基于C#的socket编程的TCP异步的实现代码
-
C#开发之Socket网络编程TCP/IP层次模型、端口及报文等探讨
-
Java编程实现基于TCP协议的Socket聊天室示例
-
C#开发之Socket网络编程TCP/IP层次模型、端口及报文等探讨
-
Python3网络编程--socket编程之Tcp编程
-
Java编程实现基于TCP协议的Socket聊天室示例
-
C# Socket编程实现简单的局域网聊天器的示例代码