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

Socket初步编程——简单实现群聊

程序员文章站 2024-02-01 18:27:34
...

初次接触到socket网络编程,也参考了网络上众前辈的文章。尝试自己也写了一下,记录下过程吧:

 

服务端:(接收客户端消息并把它们打印出来)

 

public class SocketServer {
	private List<Socket> socketList = new ArrayList<Socket>();
	 public static void main(String[] args) {  
		 SimServer ss = new SimServer();
		 try {
			ss.service();
		} catch (IOException e) {
			e.printStackTrace();
		}
	 }  
	 
	 public void service() throws IOException {
		 ServerSocket server = new ServerSocket(7001);  
		 SimServer ss = new SimServer();
		 while (true) {  
			 Socket socket = server.accept(); 
			 socketList.add(socket);
			 ServerThread st = new ServerThread(socket, socketList);
			 st.start();
		 }  
		 
	 }
	 
	 class ServerThread extends Thread {
		private Socket client;
		private List<Socket> socketList;
		public ServerThread(Socket client, List<Socket> socketList) {
			this.client = client;
			this.socketList = socketList;
		}
		
		@Override
		public void run() {
			BufferedReader in = null;  
            PrintWriter out = null;  
            try {  
                in = new BufferedReader(new InputStreamReader(client.getInputStream()));  
                while (true) {  
                    String msg = in.readLine();  
                    System.out.println(InetAddress.getLocalHost().getHostAddress() + " 客户端请求:" +msg);
//                    System.out.print("服务端请输入:");
//                    String input = new BufferedReader(new InputStreamReader(System.in)).readLine();
                    System.out.println();
                    for(int i=0; i<socketList.size(); i++) {
//                    	out = new PrintWriter(client.getOutputStream());
                    	out = new PrintWriter(socketList.get(i).getOutputStream());
                    	out.println("服务端返回:" + msg);
                    	out.println();
                    	out.flush();  
//                    out.println("Server handle: " + Arrays.toString(msg.getBytes()));
// 					  out.write("Server handle: " + Arrays.toString(msg.getBytes()));
//                    String lineSeprator = (String) java.security.AccessController.doPrivileged(
//                    		new sun.security.action.GetPropertyAction("line.separator"));
//                    out.write(lineSeprator);
//                    if (msg.equals("bye")) {  
//                        break;  
//                    }  
                    	
                    }
                }  
            } catch(IOException ex) {  
                ex.printStackTrace();  
            } finally {  
                try {  
                    in.close();  
                } catch (Exception e) {}  
                try {  
                    out.close();  
                } catch (Exception e) {}  
                try {  
//                    client.close();  
                } catch (Exception e) {}  
            }
		}
		 
	 } 
	   
}

 

客户端:(发送消息并接收消息,这个应该是异步的,所以必须创建两个线程)

public class SocketClient {
	
	class Send extends Thread {
		private Socket socket;
		public Send(Socket socket) {
			this.socket = socket;
		}
		@Override
		public void run() {
			PrintWriter out = null;
			BufferedReader input = null;
			 try {
				out = new PrintWriter(socket.getOutputStream());
				input = new BufferedReader(new InputStreamReader(System.in));
				 while (true) {
			        	System.out.print(InetAddress.getLocalHost().getHostAddress()+" 客户端请输入:");
			            String msg = input.readLine();  
			            out.println(msg);  
			            out.flush(); 
			             
			        }  
//			        socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}finally {
				try {
					if(input != null)
						 input.close(); 
					 if(out != null)
	                     out.close();
//					 if(socket != null)
//						 socket.close();
                } catch (Exception e) {}  
                
			}
		}
	}
	
	class Recv extends Thread {
		private Socket socket;
		public Recv(Socket socket) {
			this.socket = socket;
		}
		@Override
		public void run() {
			BufferedReader reader = null;
			 try {
				reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				 while (true) {
					 	System.out.println();
			            String msg = reader.readLine();  
			            System.out.println(msg);  
			           
			        }  
			} catch (IOException e) {
				e.printStackTrace();
			}finally {
				try {
					if(reader != null)
						reader.close(); 
//					 if(socket != null)
//						 socket.close();
                } catch (Exception e) {}
			}
		}
	}
	
	public static void main(String[] args) {
		SimClient sc = new SimClient();
		try {
			Socket s = new Socket("localhost", 7001);
			sc.new Recv(s).start();
			sc.new Send(s).start();
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}	
}

 

(可在另一台机器上有一个一模一样的客户端,只不过ip地址要改为服务器所在的机器的ip)

 

-----------------------------------

在此过程中,发现了几点:

1)服务端用的是ServerSocket,每当有一个客户端连接上服务端,就会触发serverSocket.accept()产生一个socket用于和客户端交互;

2)PrintWriter.write(String msg)无法把消息发出去,而PrintWriter.println(String msg)则可以,但println(String msg)相当于(要同时write lineSeprator):

 out.write("Server handle: " + Arrays.toString(msg.getBytes()));

 String lineSeprator = (String) java.security.AccessController.doPrivileged(

                  new sun.security.action.GetPropertyAction("line.separator"));

 out.write(lineSeprator);

3)服务端线程必须把socketList传进来,它才能知道有几个客户端连着它。