0
点赞
收藏
分享

微信扫一扫

Java多线程-----Socket通信


Java多线程-----Socket通信

程序分Server和Client


服务器端打开侦听的端口,一有客户端连接就创建两个新的线程来负责这个连接

一个负责客户端发送的信息(ClientMsgCollectThread 类),

另一个负责通过该Socket发送数据(ServerMsgSendThread )

Server.java代码如下:

/* 

 * 创建日期 2005-7-7 

 * 

 * TODO 要更改此生成的文件的模板,请转至 

 * 窗口 - 首选项 - Java - 代码样式 - 代码模板 

 */ 

package person.fane.MutiUser; 


import java.io.BufferedReader; 

import java.io.IOException; 

import java.io.InputStreamReader; 

import java.io.PrintWriter; 

import java.net.ServerSocket; 

import java.net.Socket; 


/** 

 * 服务器端 

 * 

 * @author Fane 

 */ 

public class Server extends ServerSocket { 


 private static final int SERVER_PORT = 10000; 


 /** 

 * 构造方法,用于实现连接的监听 

 * 

 * @throws IOException 

 */ 

 public Server() throws IOException { 

 super(SERVER_PORT); 


 try { 

 while (true) { 

 Socket socket = super.accept(); 


 new Thread(new ClientMsgCollectThread(socket), "getAndShow" 

 + socket.getPort()).start(); 

 new Thread(new ServerMsgSendThread(socket), "send" 

 + socket.getPort()).start(); 


 } 

 } catch (IOException e) { 

 e.printStackTrace(); 

 } 


 } 


 public static void main(String[] args) throws IOException { 

 new Server(); 

 } 


 /** 

 * 该类用于创建接收客户端发来的信息并显示的线程 

 * 

 * @author Fane 

 * @version 1.0.0 

 */ 

 class ClientMsgCollectThread implements Runnable { 


 private Socket client; 


 private BufferedReader in; 


 private StringBuffer inputStringBuffer = new StringBuffer("Hello"); 


 /** 

 * 得到Socket的输入流 

 * 

 * @param s 

 * @throws IOException 

 */ 

 public ClientMsgCollectThread(Socket s) throws IOException { 

 client = s; 


 in = new BufferedReader(new InputStreamReader(client 

 .getInputStream(), "GBK")); 

 } 


 public void run() { 

 try { 


 while (!client.isClosed()) { 

 inputStringBuffer.delete(0, inputStringBuffer.length()); 

 inputStringBuffer.append(in.readLine()); 


 System.out.println(getMsg(inputStringBuffer.toString())); 

 } 

 } catch (IOException e) { 

 //e.printStackTrace(); 

 System.out.println(client.toString() + " is closed!"); 


 } 

 } 


 /** 

 * 构造显示的字符串 

 * 

 * @param line 

 * @return 

 */ 

 private String getMsg(String line) { 

 return client.toString() + " says:" + line; 

 } 


 } 


 /** 

 * 该类用于创建发送数据的线程 

 * 

 * @author Fane 

 * @version 1.0.0 

 */ 

 class ServerMsgSendThread implements Runnable { 


 private Socket client; 


 private PrintWriter out; 


 private BufferedReader keyboardInput; 


 private StringBuffer outputStringBuffer = new StringBuffer("Hello"); 


 /** 

 * 得到键盘的输入流 

 * 

 * @param s 

 * @throws IOException 

 */ 

 public ServerMsgSendThread(Socket s) throws IOException { 

 client = s; 


 out = new PrintWriter(client.getOutputStream(), true); 

 keyboardInput = new BufferedReader(new InputStreamReader(System.in)); 


 } 


 public void run() { 

 try { 


 while (!client.isClosed()) { 

 outputStringBuffer.delete(0, outputStringBuffer.length()); 

 outputStringBuffer.append(keyboardInput.readLine()); 


 out.println(outputStringBuffer.toString()); 

 } 

 } catch (IOException e) { 

 //e.printStackTrace(); 

 System.out.println(client.toString() + " is closed!"); 


 } 

 } 


 } 


}



客户端:

实现基于IP地址的连接,连接后也创建两个线程来实现信息的发送和接收

/* 

 * 创建日期 2005-7-7 

 * 

 */ 

package person.fane.MutiUser; 


import java.io.BufferedReader; 

import java.io.IOException; 

import java.io.InputStreamReader; 

import java.io.PrintWriter; 

import java.net.Socket; 


/** 

 * 客户端 

 * 

 * @author Fane 

 */ 

public class Client { 


 private Socket mySocket; 


 /** 

 * 创建线程的构造方法 

 * 

 * @param IP 

 * @throws IOException 

 */ 

 public Client(String IP) throws IOException { 


 try { 

 mySocket = new Socket(IP, 10000); 

 new Thread(new ServerMsgCollectThread(mySocket), "getAndShow" 

 + mySocket.getPort()).start(); 

 new Thread(new ClientMsgSendThread(mySocket), "send" 

 + mySocket.getPort()).start(); 


 } catch (IOException e) { 

 //e.printStackTrace(); 

 System.out.println("Server.IP:" + IP 

 + " port:10000 can not be Connected"); 

 } 

 } 


 public static void main(String[] args) throws IOException { 

 try { 

 new Client(args[0]); 

 } catch (Exception e) { 

 System.out.println("输入的IP地址错误"); 

 } 

 } 


 /** 

 * 该类用于创建接收服务端发来的信息并显示的线程 

 * 

 * @author Fane 

 * @version 1.0.0 

 */ 

 class ServerMsgCollectThread implements Runnable { 


 private Socket client; 


 private BufferedReader in; 


 private StringBuffer inputStringBuffer = new StringBuffer("Hello"); 


 /** 

 * 得到Socket的输入流 

 * 

 * @param s 

 * @throws IOException 

 */ 

 public ServerMsgCollectThread(Socket s) throws IOException { 

 client = s; 


 in = new BufferedReader(new InputStreamReader(client 

 .getInputStream(), "GBK")); 

 } 


 public void run() { 

 try { 


 while (!client.isClosed()) { 

 inputStringBuffer.delete(0, inputStringBuffer.length()); 

 inputStringBuffer.append(in.readLine()); 

 System.out.println(getMsg(inputStringBuffer.toString())); 

 } 

 } catch (IOException e) { 

 //e.printStackTrace(); 

 System.out.println(client.toString() + " is closed!"); 

 System.exit(0); 

 } 

 } 


 /** 

 * 构造输入字符串 

 * 

 * @param line 

 * @return 

 */ 

 private String getMsg(String line) { 

 return client.toString() + " says:" + line; 

 } 


 } 


 /** 

 * 该类用于创建发送数据的线程 

 * 

 * @author Fane 

 * @version 1.0.0 

 */ 

 class ClientMsgSendThread implements Runnable { 


 private Socket client; 


 private PrintWriter out; 


 private BufferedReader keyboardInput; 


 private StringBuffer outputStringBuffer = new StringBuffer("Hello"); 


 /** 

 * 得到键盘的输入流 

 * 

 * @param s 

 * @throws IOException 

 */ 

 public ClientMsgSendThread(Socket s) throws IOException { 

 client = s; 


 out = new PrintWriter(client.getOutputStream(), true); 

 keyboardInput = new BufferedReader(new InputStreamReader(System.in)); 


 } 


 public void run() { 

 try { 


 while (!client.isClosed()) { 

 outputStringBuffer.delete(0, outputStringBuffer.length()); 

 outputStringBuffer.append(keyboardInput.readLine()); 


 out.println(outputStringBuffer.toString()); 

 } 

 out.println("--- See you, bye! ---"); 

 } catch (IOException e) { 

 //e.printStackTrace(); 

 System.out.println(client.toString() + " is closed!"); 

 System.exit(0); 

 } 

 } 


 } 


}




该程序基本通信没有问题

但是有如下bug,请各位提出宝贵意见

1:在cmd模式下,用Ctrl+C来结束客户端程序,服务器先出现收到为null,再出现断开连接的提示,在直接关闭命令行时就只提示断开连接,不知道这个null何来

Socket[addr=/192.168.0.12,port=2205,localport=10000] says:null
Socket[addr=/192.168.0.12,port=2205,localport=10000] is closed!

2:假如打开5个命令行并连接成功后,发送信息时,服务器能收到所有5个客户端来的信息,但是5个客户端只能轮流收到服务器的信息,也就是说我每打一个"Hello"+Enter,只有一个客户端能收到消息,重复5次,这样每个客户端都能收到一次,这个本不奇怪(设计的问题,不好意思),但是我关闭了其中4个以后,还是要发5次客户端才能收到一次消息,也就是说其他4个Socket关闭了,但是线程没有关闭,不知道怎样才能解决线程的这个问题(在一台机子上试验出现这个问题)

发送:

Socket[addr=/192.168.0.12,port=2201,localport=10000] is closed!
Socket[addr=/192.168.0.12,port=2203,localport=10000] says:null
Socket[addr=/192.168.0.12,port=2203,localport=10000] is closed!
Socket[addr=/192.168.0.12,port=2204,localport=10000] says:null
Socket[addr=/192.168.0.12,port=2204,localport=10000] is closed!
Socket[addr=/192.168.0.12,port=2205,localport=10000] says:null
Socket[addr=/192.168.0.12,port=2205,localport=10000] is closed!

hehhe
hehe
hehe
hehe
hehe

接收:Socket[addr=/192.168.0.12,port=10000,localport=2206] says:hehe

(前面4个hehe丢失了)

其它bug也在查找中.......

举报

相关推荐

0 条评论