欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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();
					}
				}
			}
		}
}