使用Socket实现最简单的聊天功能

平时开发中会经常接触到Socket,其使用也不复杂,在阻塞Socket中,主要是理解什么操作会导致阻塞。serverSocket的accept方法会一直阻塞直到有客户端Socket进入,处理时最好是另开一个线程给它。


把聊天系统简单化,一个服务器是必需的,下面称之为A,用来传输两个进行聊天的客户端之间的消息,下面称为B和C。B需要一个标志位,用于检查是否刚登录,若是,自动发送自己的ID和消息给A,告诉A我已上线,然后A中需要有一个客户列表用来保存在线的客户ID。接下来B发送消息给C前,要把C的ID也发送给A,这样才能进行B和C之间的正常通信。当然,A还要先根据C的ID检查客户列表中是否有C,已确定C是否在线上;若C不在线上就要告诉B,若在,B和C通信建立,可以开始聊天了。


===========================================================传说中的分界线=============================================================

服务器代码:


package server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;

public class ServerChat {

	private static ServerSocket server;
	private static volatile HashMap
   
   
    
     userQueue = new HashMap
    
    
     
     ();

	public ServerChat(int port, int backlog) {
		try {
			server = new ServerSocket(port);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 用户聊天的核心方法
	 */
	private static void processChat() {

		// boolean shutdown = false;
		// String received = null;
		System.out.println("等待用户接入。。。");
		try {

			while (true) {
				Socket client = server.accept();
				System.out.println("已有用户接入,等待信息。。。");

				new Thread(new Runnable() {

					TransferMsgThread tranUserInfo = new TransferMsgThread(
							client);
					String send = null;
					boolean firstTime = true;
					String userID = null;
					String friendID = null;

					@Override
					public void run() {
						System.out.println("即将进入while循环。。。");

						while (true) {

							send = tranUserInfo.sendMessage();
							// 客户上线时,后台主动发送消息通知服务器客户已上线

							if (send != null) {
								System.out.println("info content :" + send);

								if (firstTime
										&& send.substring(send.indexOf(':') + 1)
												.equalsIgnoreCase("I am onLine")) {
									userID = send.substring(0,
											send.indexOf(":"));
									send = send.substring(send.indexOf(":") + 1);
									
									// 将在线用户添加进表中
									if (userQueue.size() == 0
											|| userQueue.get(userID) == null) {
										userQueue.put(userID, client);
									}
									
									firstTime = false;
									System.out.println("userQueue get "
											+ userQueue.get(userID));

								} else {

									friendID = send.substring(0,
											send.indexOf(":"));
									System.out.println("friendID == "
											+ friendID);

									send = send.substring(send.indexOf(":") + 1);

									Socket friend = (Socket) userQueue
											.get(friendID);
									if (friend == null) {
										tranUserInfo.receiveMessage("对方未上线!");
									} else {
										if (send.equals("shutdown")) {
											// shutdown = true;
											// break;
										}
										TransferMsgThread tranFriendInfo = new TransferMsgThread(
												friend);
										tranFriendInfo.receiveMessage(userID
												+ ": " + send);
									}
								}

							} else {
								if (firstTime) {
									firstTime = false;
									System.out.println("message is null !");
								}
							}

						}

					}
				}).start();

			}
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		// closeConnect();
	}

	protected static void closeConnect() {
		try {
			server.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {

		new ServerChat(8899, 100).processChat();
	}

}

    
    
   
   


package server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class TransferMsgThread {
	private volatile String message;

	private Socket client;

	public TransferMsgThread(Socket client) {
		this.client = client;
	}

	public String sendMessage() {

		try {
			message = sendMessageToOtherClient(client);

		} catch (IOException e) {
			e.printStackTrace();
		}

		System.out.println("message == " + message);
		return message;
	}

	public void receiveMessage(String msg) {

		try {
			getMessageFormOtherClient(client, msg);
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	protected void getMessageFormOtherClient(Socket client, String msg)
			throws IOException {
		BufferedWriter writer;
		writer = new BufferedWriter(new OutputStreamWriter(
				client.getOutputStream(), "UTF-8"));
		writer.write(msg + "EOF");
		writer.newLine();
		writer.flush();
	}

	protected static String sendMessageToOtherClient(Socket client)
			throws IOException {
		BufferedReader reader;
		reader = new BufferedReader(new InputStreamReader(
				client.getInputStream(), "UTF-8"));
		StringBuffer msg = new StringBuffer();
		String tmp = null;
		int index = -1;
		
		while ((tmp = reader.readLine()) != null) {
			if ((index = tmp.indexOf("EOF")) != -1) {
				tmp = tmp.substring(0, index);
				msg.append(tmp);
				System.out.println("break out while!");
				break;
			}
			msg.append(tmp);
		}

		return msg.toString();
	}
}


客户端代码:


package Test;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

public class Client {

	private String host;;
	private int port;;
	private Socket client;

	public Client() {
		this( "127.0.0.1", 8899);
	}

	public Client(String host, int port) {
		this.host = host;
		this.port = port;
		try {
			client = new Socket(host, port);
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void writeInfo(String info) {
		BufferedWriter writer = null;
		try {
			writer = new BufferedWriter( new OutputStreamWriter(client.getOutputStream(),
					"UTF-8"));
			writer.write(info);
			writer.newLine();
			writer.flush();

		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
//		finally {
//			if (writer != null) {
//				try {
//					writer.close();
//				} catch (IOException e) {
//					// TODO Auto-generated catch block
//					e.printStackTrace();
//				}
//			}
//		}
	}

	public String readInfo() throws SocketTimeoutException{
		
		String info = null;
		BufferedReader br = null;
		
		try {
			br = new BufferedReader(new InputStreamReader(
					client.getInputStream(), "UTF-8"));
			
//			client.setSoTimeout(5 * 1000);
			
			StringBuffer sb = new StringBuffer();
			String temp;
			int index;
			
			while((temp = br.readLine()) != null) {
				if((index = temp.indexOf("EOF")) != -1) {
					sb.append(temp.substring(0, index));
					break;
				}
				sb.append(temp);
			}
			
			info = sb.toString();
			
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
//		finally {
//			if(br != null) {
//				try {
//					br.close();
//				} catch (IOException e) {
//					e.printStackTrace();
//				}
//				
//			}
//		}

		return info;
	}
	
	public void clientDown() {
		if(client != null) {
			try {
				client.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

package Test;

import java.net.SocketTimeoutException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;


public class MainTest {
	
	private static Client client;
	private static SimpleDateFormat format;
	
	
	public static void main(String[] args) {
		
		
		System.out.println("start client");
		
		Scanner input = new Scanner(System.in);
		String line = null;
		
		System.out.println("请输入你的ID:");
		 line = input.nextLine();
		client = new Client();
		client.writeInfo(line + ":I am onLine" + "EOF");
		
		new Thread() {
			public void run() {
				while(true) {
					String info;
					try {
						info = client.readInfo();
						if(info != null) {
							System.out.println(info);
						}
					} catch (SocketTimeoutException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
			};
		}.start();
		
		System.out.println("请输入你朋友的ID:");
		String id = input.nextLine();
		
		System.out.println("聊天开始:");
		
		new Thread() {
			public void run() {
				while(true) {
					String line = input.nextLine();
					client.writeInfo(id + ":" + line + "EOF");
					if(line.equalsIgnoreCase("shutdown")) {
						break;
					}
				}
			};
		}.start();
		
		
//		Timer timer = new Timer(true);
//		
//		TimerTask task = new TimerTask() {
//
//			public void run() {
//				plane();
//			}
//			
//		};
//		
//		timer.schedule(task, 2 * 1000, 5 * 1000);
//		
//		try {
//			Thread.sleep(50 * 1000);
//		} catch (InterruptedException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
	}
	
	public static void plane() {
		System.out.println("client plane starting");
		
		format = new SimpleDateFormat(
				"yy-MM-dd HH:mm:ss");
		
		client = new Client();
		client.writeInfo(format.format(new Date()));
		
		try {
			System.out.println("info show by client,form server"
					+ client.readInfo());
		} catch (SocketTimeoutException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
//		client.clientDown();
		
	System.out.println("client real in the end!");
}
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值