TCP Socket编程--聊天雏形

好久没有写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();
					}
				}
			}
		}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值