java socket多线程通讯

转载自:http://blog.csdn.net/yangyuankp/article/details/7936384

  

    先来看一段单线程的原始代码(代码中有详细的注释):

 

         服务器(TCPServer.java):


[java]  view plain copy print ?
  1. import java.net.*;  
  2. import java.io.*;  
  3.   
  4. public class TCPServer{  
  5.   public static void main(String[] args) throws Exception{  
  6.     ServerSocket ss = new ServerSocket(5566); //创建一个Socket服务器,监听5566端口  
  7.     int i=0;  
  8.     //利用死循环不停的监听端口  
  9.     while(true){  
  10.       Socket s = ss.accept(); //利用Socket服务器的accept()方法获取客户端Socket对象。  
  11.       i++;  
  12.       System.out.println("第" + i +"个客户端成功连接!");  
  13.       DataInputStream dis = new DataInputStream(s.getInputStream()); //获取客户端Socket对象的输入流,并在外边加一层DataInputStream管道,目的是方便读取数据  
  14.       System.out.println(dis.readUTF()); //读出流中的数据,DataInputStream对象的readUTF()方法可以读出流中的数据,而且支持中文  
  15.       dis.close(); //关闭管道连接  
  16.       s.close(); //关闭Socket连接  
  17.     }  
  18.   }  
  19.   
  20. }  

        客户端(TCPClient.java):


[java]  view plain copy print ?
  1. import java.net.*;  
  2. import java.io.*;  
  3.   
  4. public class TCPClient{  
  5.   public static void main(String[] args) throws Exception{  
  6.     Socket s = new Socket("192.168.24.177",5566); //创建一个Socket对象,连接IP地址为192.168.24.177的服务器的5566端口  
  7.     DataOutputStream dos = new DataOutputStream(s.getOutputStream()); //获取Socket对象的输出流,并且在外边包一层DataOutputStream管道,方便输出数据  
  8.     dos.writeUTF("客户端消息"); //DataOutputStream对象的writeUTF()方法可以输出数据,并且支持中文  
  9.     dos.flush(); //确保所有数据都已经输出  
  10.     dos.close(); //关闭输出流  
  11.     s.close(); //关闭Socket连接  
  12.   }  
  13. }  


        以上代码利用Socket对象和ServerSocket对象进行简单的网络交互,即客户端通过DataOutputStream对象的writeUTF()方法向服务器发送消息,服务器利用DataInputStream对象的readUTF()方法读出数据。

        看上去挺好,但ServerSocket对象的accept()方法是阻塞的方法,它会一直等待,直到有客户端连接。

        同理,DataInputStream对象的readUTF()方法也是阻塞的方法,它也会一直等待,直到客户端调用writeUTF()方法。

        因此,假如某个客户端成功连接服务器,但是迟迟不调用writeUTF()方法发送数据,服务器就要一直等待,直到客户端调用writeUTF()方法为止,此期间整个服务器是阻塞的,无法再接受其他客户端连接,显然这不符合实际情况。

        要解决这个问题,当然要用多线程。

        如果每个客户端都独有一个线程,让readUTF()方法阻塞客户端独有的线程,而不去阻塞服务器主线程,这样服务器就可以同时接受多个客户端连接,而不用考虑客户端何时调用writeUTF()方法发送数据。代码如下:

 

        服务器(TCPServer.java):


[java]  view plain copy print ?
  1. import java.net.*;  
  2. import java.io.*;  
  3.   
  4. public class TCPServer{  
  5.   public static void main(String[] args) throws Exception{  
  6.     ServerSocket ss = new ServerSocket(5566); //创建一个Socket服务器,监听5566端口  
  7.     int i=0;  
  8.     //利用死循环不停的监听端口  
  9.     while(true){  
  10.       Socket s = ss.accept();//利用Socket服务器的accept()方法获取客户端Socket对象。  
  11.       i++;  
  12.       System.out.println("第" + i +"个客户端成功连接!");  
  13.       Client c = new Client(i,s); //创建客户端处理线程对象  
  14.       Thread t =new Thread(c); //创建客户端处理线程  
  15.       t.start(); //启动线程  
  16.     }  
  17.   }  
  18.   
  19. }  
  20.   
  21. //客户端处理线程类(实现Runnable接口)  
  22. class Client implements Runnable{  
  23.   int clientIndex = 0//保存客户端id  
  24.   Socket s = null//保存客户端Socket对象  
  25.     
  26.   Client(int i,Socket s){  
  27.     clientIndex = i;  
  28.     this.s = s;  
  29.   }  
  30.     
  31.   public void run(){  
  32.     //打印出客户端数据  
  33.     try{  
  34.       DataInputStream dis = new DataInputStream(s.getInputStream());  
  35.       System.out.println("第" + clientIndex + "个客户端发出消息:" + dis.readUTF());  
  36.       dis.close();  
  37.       s.close();  
  38.     }  
  39.     catch(Exception e)  
  40.     {}  
  41.   }  
  42. }  

        客户端(TCPClient.java):


[java]  view plain copy print ?
  1. import java.net.*;  
  2. import java.io.*;  
  3.   
  4. public class TCPClient{  
  5.   public static void main(String[] args) throws Exception{  
  6.     Socket s = new Socket("192.168.24.177",5566); //创建一个Socket对象,连接IP地址为192.168.24.177的服务器的5566端口  
  7.     DataOutputStream dos = new DataOutputStream(s.getOutputStream()); //获取Socket对象的输出流,并且在外边包一层DataOutputStream管道,方便输出数据  
  8.     Thread.sleep((int)(Math.random()*3000)); //让客户端不定时向服务器发送消息  
  9.     dos.writeUTF("客户端消息"); //DataOutputStream对象的writeUTF()方法可以输出数据,并且支持中文  
  10.     dos.flush(); //确保所有数据都已经输出  
  11.     dos.close(); //关闭输出流  
  12.     s.close(); //关闭Socket连接  
  13.   }  
  14. }  


        运行结果如下(参考结果,不一定相同!):


        明显看出第2、3、4客户端都没有向服务器端发出消息,但都成功连接,而且第2、3、4客户端向服务器发出消息也没有顺序。

        通过多线程,实现了多个客户端同时连接服务器,并且服务器能实时处理多个客户端发出的消息。

        以上仅仅是作为初学者的一些想法,仅供参考!


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的多线程Socket通讯的实例,其中服务器和客户端之间可以进行简单的字符串通讯服务器端代码: ``` import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class MultiThreadedServer { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(1234); while (true) { Socket socket = serverSocket.accept(); Thread t = new Thread(new ServerThread(socket)); t.start(); } } catch (IOException e) { e.printStackTrace(); } } private static class ServerThread implements Runnable { private Socket socket; public ServerThread(Socket socket) { this.socket = socket; } public void run() { try { BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); String line; while ((line = in.readLine()) != null) { System.out.println("Received: " + line); out.println("Server received: " + line); } in.close(); out.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } ``` 客户端代码: ``` import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; public class MultiThreadedClient { public static void main(String[] args) { try { Socket socket = new Socket("localhost", 1234); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); BufferedReader consoleIn = new BufferedReader(new InputStreamReader(System.in)); String line; while ((line = consoleIn.readLine()) != null) { out.println(line); System.out.println(in.readLine()); } in.close(); out.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` 运行这两个程序后,在客户端中输入字符串,服务器会将其原样返回。在服务器端控制台上也可以看到接收到的字符串。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值