Java Socket编程

1.简述:

Java Socket编程时对于TCP/IP 协议层的通信进行封装,简化了相关的一些操作。//待续

2.Socket 通信时序图

 Java Socket编程

  3.Socket 数据流的交互

Java Socket编程

 

4.单客户端和服务器通信的简单例子:

服务器端代码:

[java] view plain copy
  1. package com.lou.socket;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStreamReader;  
  6. import java.io.PrintWriter;  
  7. import java.net.InetSocketAddress;  
  8. import java.net.ServerSocket;  
  9. import java.net.Socket;  
  10.   
  11. public class TestServer {  
  12. public static void main(String[] args) throws IOException {  
  13.     //1.创建一个Server Socket  
  14.     ServerSocket server = new ServerSocket();  
  15.     // 2.绑定监听指定的端口  
  16.     InetSocketAddress address = new InetSocketAddress("localhost",18824);  
  17.     server.bind(address);  
  18.     // 3.接受此端口的通信请求  
  19.     Socket socket = server.accept();  
  20.     // 在没有客户端对其进行相应前,下面的代码不会执行,将一直阻塞  
  21.       
  22.     //服务器端的输出流和输入流获取  
  23.     BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  24.     PrintWriter writer = new PrintWriter(socket.getOutputStream(),true);  
  25.       
  26.     //来自键盘的输入数据  
  27.     BufferedReader keyword=new BufferedReader(new InputStreamReader(System.in));  
  28.       
  29.     while(true)  
  30.     {  
  31.         if(reader.ready())  
  32.         {  
  33.             // 捕捉来自客户端发来的消息     客户端没有发消息过来时,reader.ready() 为false, 循环检测是否有数据,有测打印出来  
  34.             String info = reader.readLine();  
  35.             System.out.println("Client:"+info);  
  36.         }  
  37.         if(keyword.ready())  
  38.         {  
  39.             //捕获来自服务器端另外一个输入流 : 键盘的数据。如果有数据,则发送给客户端  
  40.             String  test = keyword.readLine();  
  41.             writer.println(test);  
  42.             System.out.println("Server:"+test);  
  43.         }  
  44.           
  45.     }  
  46. }  
  47. }  


客户端代码:

[java] view plain copy
  1. import java.io.BufferedReader;  
  2. import java.io.IOException;  
  3. import java.io.InputStreamReader;  
  4. import java.io.PrintWriter;  
  5. import java.net.InetSocketAddress;  
  6. import java.net.Socket;  
  7. import java.net.UnknownHostException;  
  8.   
  9.   
  10. public class ClientSocket {  
  11.   
  12.     public static void main(String[] args) throws UnknownHostException, IOException {  
  13.           
  14.         //1.创建一个Server Socket  
  15.         Socket socket = new Socket();  
  16.           
  17.         // 2.连接到指定的 server socket,指定IP 和端口号  
  18.         InetSocketAddress address = new InetSocketAddress("localhost",18824);  
  19.         socket.connect(address);  
  20.           
  21.         // 3.连接成功后,获取相应的输入输出流,进行数据交互  
  22.         BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  23.         PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);  
  24.           
  25.         BufferedReader keyword=new BufferedReader(new InputStreamReader(System.in));  
  26.           
  27.         while(true)  
  28.         {  
  29.             // 捕捉来自服务器端发来的消息   服务器端没有发消息过来时,br.ready() 为false, 循环检测是否有数据,有测打印出来  
  30.             if(br.ready())  
  31.             {  
  32.                 String info = br.readLine();  
  33.                 System.out.println("Server:"+info);  
  34.             }  
  35.               
  36.             //捕获来自服务器端另外一个输入流 : 键盘的数据。如果有数据,则发送给服务器端  
  37.             if(keyword.ready())  
  38.             {  
  39.                 String  test = keyword.readLine();  
  40.                 pw.println(test);  
  41.                 System.out.println("Client:"+test);  
  42.             }  
  43.               
  44.         }  
  45.           
  46.   
  47.     }  
  48.   
  49. }  


 运行结果:

 Java Socket编程Java Socket编程

       

5.Socket 多客户端单服务器之间的通信:

       上面的这个例子只能支持一个服务器端和一个客户端的通信,因为 客户端内 server.accept() 方法只执行了一次,只能返回一个Socket 连接。可以在服务端接受多个Socket,这时候的Socket应当放在一个线程里,让它有生命周期,来使用客户端和服务端的*通信。

 

[java] view plain copy
  1. package com.lou.socket;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.InetSocketAddress;  
  5. import java.net.ServerSocket;  
  6. import java.net.Socket;  
  7.   
  8. public class TestServer {  
  9. public static void main(String[] args) throws IOException {  
  10.     //1.创建一个Server Socket  
  11.     ServerSocket server = new ServerSocket();  
  12.     // 2.绑定监听指定的端口  
  13.     InetSocketAddress address = new InetSocketAddress("localhost",18824);  
  14.     server.bind(address);  
  15.     // 3.接受此端口的通信请求  
  16.       
  17.     while(true)  
  18.     {  
  19.         //循环调用accept方法,返回相应的Socket  
  20.         Socket socket = server.accept();  
  21.         //使用线程,将每一个Socket都封装到线程内,这个每个接受的Socket可以*的跟服务器通信了  
  22.         new Thread(new SocketHandler(socket)).start();  
  23.     }  
  24.   
  25. }  
  26. }  


 

[java] view plain copy
  1. package com.lou.socket;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStreamReader;  
  6. import java.io.PrintWriter;  
  7. import java.net.Socket;  
  8.   
  9. public class SocketHandler implements Runnable {  
  10.   
  11.     private Socket socket;  
  12.       
  13.     public SocketHandler(Socket socket)  
  14.     {  
  15.         this.socket =socket;  
  16.     }  
  17.     @Override  
  18.     public void run() {  
  19.         try {  
  20.             BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  21.             PrintWriter writer = new PrintWriter(socket.getOutputStream(),true);  
  22.             //来自键盘的输入数据  
  23.             BufferedReader keyword=new BufferedReader(new InputStreamReader(System.in));  
  24.             boolean flag = true;  
  25.               
  26.             while(flag)  
  27.             {  
  28.                 if(reader.ready())  
  29.                 {  
  30.                     // 捕捉来自客户端发来的消息     客户端没有发消息过来时,reader.ready() 为false, 循环检测是否有数据,有测打印出来  
  31.                     String info = reader.readLine();  
  32.                     System.out.println("Client "+socket.getPort() +":"+info);  
  33.                       
  34.                     //如果对方输入BYE,关闭回话  
  35.                     if("BYE" == info)  
  36.                     {  
  37.                         socket.close();  
  38.                         flag = false;  
  39.                     }  
  40.                 }  
  41.                 if(keyword.ready())  
  42.                 {  
  43.                     //捕获来自服务器端另外一个输入流 : 键盘的数据。如果有数据,则发送给客户端  
  44.                     String  test = keyword.readLine();  
  45.                     writer.println(test);  
  46.                     System.out.println("Server:"+test);  
  47.                       
  48.                       
  49.                 }  
  50.                   
  51.             }  
  52.               
  53.         } catch (IOException e) {  
  54.             e.printStackTrace();  
  55.         }  
  56.   
  57.     }  
  58.   
  59. }  


 

[java] view plain copy
  1. import java.io.BufferedReader;  
  2. import java.io.IOException;  
  3. import java.io.InputStreamReader;  
  4. import java.io.PrintWriter;  
  5. import java.net.InetSocketAddress;  
  6. import java.net.Socket;  
  7. import java.net.UnknownHostException;  
  8.   
  9.   
  10. public class ClientSocket {  
  11.   
  12.     public static void main(String[] args) throws UnknownHostException, IOException {  
  13.           
  14.         //1.创建一个Server Socket  
  15.         Socket socket = new Socket();  
  16.           
  17.         // 2.连接到指定的 server socket,指定IP 和端口号  
  18.         InetSocketAddress address = new InetSocketAddress("localhost",18824);  
  19.         socket.connect(address);  
  20.           
  21.         // 3.连接成功后,获取相应的输入输出流,进行数据交互  
  22.         BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  23.         PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);  
  24.           
  25.         BufferedReader keyword=new BufferedReader(new InputStreamReader(System.in));  
  26.           
  27.         while(true)  
  28.         {  
  29.             // 捕捉来自服务器端发来的消息   服务器端没有发消息过来时,br.ready() 为false, 循环检测是否有数据,有测打印出来  
  30.             if(br.ready())  
  31.             {  
  32.                 String info = br.readLine();  
  33.                 System.out.println("Server:"+info);  
  34.             }  
  35.               
  36.             //捕获来自服务器端另外一个输入流 : 键盘的数据。如果有数据,则发送给服务器端  
  37.             if(keyword.ready())  
  38.             {  
  39.                 String  test = keyword.readLine();  
  40.                 if("BYE" == test)  
  41.                 {  
  42.                     br.close();  
  43.                     pw.close();  
  44.                     socket.close();  
  45.                 }  
  46.                 pw.println(test);  
  47.                 System.out.println("Client:"+test);  
  48.             }  
  49.               
  50.         }  
  51.           
  52.   
  53.     }  
  54.   
  55. }  


 Java Socket编程

 

6. 简易聊天工具的实现:

    实现的主要思路:

   a.在服务器端设置一个主线程,监听特定的一个接口,为每一个socket请求创建一个对话框和相应的处理。

   主线程MainThread代码:

[java] view plain copy
  1. package com.lou.socket;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.InetSocketAddress;  
  5. import java.net.ServerSocket;  
  6. import java.net.Socket;  
  7. import java.util.ArrayList;  
  8. import java.util.List;  
  9.   
  10. /* 
  11.  * server的主线程,监听socket端口,为每一个Socket 创建一个对话框 
  12.  */  
  13. public class MainThread extends Thread{  
  14.       
  15.     public List<Socket> sockets = new ArrayList<Socket>();  
  16.     @Override  
  17.     public void run() {  
  18.         //1.创建一个Server Socket  
  19.         ServerSocket server =null;  
  20.         try {  
  21.             server = new ServerSocket();  
  22.             InetSocketAddress address = new InetSocketAddress("localhost",18824);  
  23.             server.bind(address);  
  24.             while(true)  
  25.             {  
  26.                   
  27.                 //循环调用accept方法,返回相应的Socket  
  28.                 Socket socket = server.accept();  
  29.                 sockets.add(socket);  
  30.                   
  31.                 // 为每一个请求的Socket提供 界面 "会话"  
  32.                 ServerGUI serverGUI = new ServerGUI(socket);  
  33.                 //创建监听socket 数据流输入信息,有数据输入,则更新到GUI  
  34.                 new Thread(new SocketInfoUpdater(serverGUI)).start();  
  35.             }  
  36.               
  37.         } catch (IOException e) {  
  38.             // TODO Auto-generated catch block  
  39.             e.printStackTrace();  
  40.         }  
  41.           
  42.     }  
  43.   
  44.     public static void main(String[] args) {  
  45.   
  46.         new MainThread().start();  
  47.     }  
  48.   
  49. }  


b.定义一个监听线程,用来处理 socket发送过来的数据信息,及时更新到GUI上,和 server GUI 上的发送按钮的事件相应,来发送数据。

事件和输入流监听线程SocketInfoUpdater.java

[java] view plain copy
  1. package com.lou.socket;  
  2.   
  3. import java.awt.event.ActionEvent;  
  4. import java.awt.event.ActionListener;  
  5. import java.io.BufferedReader;  
  6. import java.io.IOException;  
  7. import java.io.InputStreamReader;  
  8. import java.io.PrintWriter;  
  9. import java.net.Socket;  
  10. import java.text.SimpleDateFormat;  
  11. import java.util.Date;  
  12.   
  13. /* 
  14.  * 此线程监听serverGUI所拥有的socket是否有数据输入,如果有更新,则更新到GUI上 
  15.  */  
  16. public class SocketInfoUpdater implements Runnable,ActionListener{  
  17.   
  18.     ServerGUI server;  
  19.       
  20.     SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  21.     public SocketInfoUpdater(ServerGUI server)  
  22.     {  
  23.         this.server = server;  
  24.     }  
  25.     @Override  
  26.     public void run() {  
  27.         Socket socket = server.socket;  
  28.         while(true)  
  29.         {  
  30.                 try {  
  31.                     BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  32.                     if(reader.ready())  
  33.                     {  
  34.                         String info = reader.readLine();  
  35.                         server.outputArea.append("Client-" +socket.getPort()+" at " + f.format(new Date()) + "\n");  
  36.                         server.outputArea.append("  "+info +"\n");  
  37.                     }  
  38.                       
  39.                 } catch (IOException e) {  
  40.                     e.printStackTrace();  
  41.                 }  
  42.                   
  43.         }  
  44.     }  
  45.       
  46.     //设置发送按钮监听,事件相应  
  47.     @Override  
  48.     public void actionPerformed(ActionEvent e) {  
  49.         String temp = server.inputArea.getText();  
  50.         SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  51.         server.outputArea.append("Client "+server.socket.getLocalPort() +" at " + f.format(new Date()) + "\n");  
  52.         server.outputArea.append("  " + temp + "\n");  
  53.         this.sendInfo(temp);  
  54.         server.inputArea.setText("");  
  55.   
  56.     }  
  57.   
  58.     private void sendInfo(String s) {  
  59.         try {  
  60.             PrintWriter pw = new PrintWriter(server.socket.getOutputStream(),  
  61.                     true);  
  62.             pw.println(s);  
  63.         } catch (IOException e) {  
  64.             e.printStackTrace();  
  65.         }  
  66.     }  
  67. }  

 

c. 服务器端界面的设计:

 

 Java Socket编程

服务器端界面设计 ServerGUI.java:

[java] view plain copy
  1. package com.lou.socket;  
  2.   
  3. import java.awt.BorderLayout;  
  4. import java.awt.Container;  
  5. import java.awt.GridLayout;  
  6. import java.io.IOException;  
  7. import java.net.Socket;  
  8.   
  9. import javax.swing.JButton;  
  10. import javax.swing.JFrame;  
  11. import javax.swing.JPanel;  
  12. import javax.swing.JScrollPane;  
  13. import javax.swing.JTextArea;  
  14.   
  15. public class ServerGUI extends JFrame {  
  16.   
  17.     public final Socket socket;  
  18.     //交互对话框中接收数据显示区  
  19.     final JTextArea outputArea = new JTextArea(7070);  
  20.     //输入区域  
  21.     final JTextArea inputArea = new JTextArea(7070);  
  22.     final JScrollPane outputScroll = new JScrollPane(outputArea);  
  23.     final JScrollPane inputScroll = new JScrollPane(inputArea);  
  24.   
  25.     public ServerGUI(Socket socket1) throws IOException {  
  26.           
  27.         //传入特定的socket  
  28.         this.socket = socket1;  
  29.         this.setTitle("Server");  
  30.         Container container = getContentPane();  
  31.         JPanel pane = new JPanel();  
  32.         container.setLayout(new BorderLayout());  
  33.         pane.setLayout(new GridLayout(2155));  
  34.   
  35.         inputScroll.setAutoscrolls(true);  
  36.         outputScroll.setAutoscrolls(true);  
  37.         pane.add(outputScroll);  
  38.   
  39.         pane.add(inputScroll);  
  40.   
  41.         setSize(300300);  
  42.         container.add(pane, BorderLayout.CENTER);  
  43.           
  44.         JButton send = new JButton("Send");  
  45.         //为发送按钮设置发送事件  
  46.         SocketInfoUpdater updater = new SocketInfoUpdater(this);  
  47.         send.addActionListener(updater);  
  48.         container.add(send, BorderLayout.SOUTH);  
  49.         setDefaultCloseOperation(3);  
  50.         setVisible(true);  
  51.     }  
  52. }  


 

客户端的设计:

客户端的实现比较简单,创建一个界面,然后配一个监听输入流和处理事件的监听线程就可以了。

Java Socket编程

a.客户端GUI,ClientGUI代码:

[java] view plain copy
  1. import java.awt.BorderLayout;  
  2. import java.awt.Container;  
  3. import java.awt.GridLayout;  
  4. import java.io.IOException;  
  5. import java.net.InetSocketAddress;  
  6. import java.net.Socket;  
  7.   
  8. import javax.swing.JButton;  
  9. import javax.swing.JFrame;  
  10. import javax.swing.JPanel;  
  11. import javax.swing.JScrollPane;  
  12. import javax.swing.JTextArea;  
  13.   
  14. public class ClientGUI extends JFrame {  
  15.   
  16.     Socket socket = null;  
  17.     final JTextArea outputArea = new JTextArea(7070);  
  18.     final JTextArea inputArea = new JTextArea(7070);  
  19.     final JScrollPane outputScroll = new JScrollPane(outputArea);  
  20.     final JScrollPane inputScroll = new JScrollPane(inputArea);  
  21.   
  22.     public ClientGUI() throws IOException {  
  23.   
  24.         this.setTitle("Client");  
  25.         this.initClientSocket();  
  26.         SocketInfoUpdater updater = new SocketInfoUpdater(this);  
  27.         new Thread(updater).start();  
  28.         Container container = getContentPane();  
  29.         JPanel pane = new JPanel();  
  30.         container.setLayout(new BorderLayout());  
  31.         pane.setLayout(new GridLayout(2155));  
  32.   
  33.         inputScroll.setAutoscrolls(true);  
  34.         outputScroll.setAutoscrolls(true);  
  35.         pane.add(outputScroll);  
  36.   
  37.         pane.add(inputScroll);  
  38.   
  39.         setSize(300300);  
  40.         container.add(pane, BorderLayout.CENTER);  
  41.         JButton send = new JButton("Send");  
  42.         send.addActionListener(updater);  
  43.         container.add(send, BorderLayout.SOUTH);  
  44.   
  45.         setDefaultCloseOperation(3);  
  46.   
  47.         setVisible(true);  
  48.   
  49.   
  50.     }  
  51.   
  52.     /* 
  53.      * 初始化socket 
  54.      */  
  55.     private void initClientSocket() {  
  56.         // 1.创建一个Server Socket  
  57.         socket = new Socket();  
  58.   
  59.         // 2.连接到指定的 server socket,指定IP 和端口号  
  60.         InetSocketAddress address = new InetSocketAddress("localhost"18824);  
  61.         try {  
  62.             socket.connect(address);  
  63.         } catch (IOException e) {  
  64.             e.printStackTrace();  
  65.         }  
  66.     }  
  67.   
  68.     public static void main(String[] args) throws IOException {  
  69.         new ClientGUI();  
  70.   
  71.     }  
  72.   
  73. }  


b. 输入流监听和发送数据的监听线程SocketInfoUpdater.java (这个类其实和服务器端上的基本上一样,之所以把它贴出来是考虑到在后续的开发设计中,Server 端和Client端的机制有所不同):

[java] view plain copy
  1. import java.awt.event.ActionEvent;  
  2. import java.awt.event.ActionListener;  
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStreamReader;  
  6. import java.io.PrintWriter;  
  7. import java.net.Socket;  
  8. import java.text.SimpleDateFormat;  
  9. import java.util.Date;  
  10.   
  11. public class SocketInfoUpdater implements Runnable ,ActionListener{  
  12.   
  13.     ClientGUI client;  
  14.     public SocketInfoUpdater(ClientGUI client)  
  15.     {  
  16.         this.client = client;  
  17.     }  
  18.       
  19.       
  20.     @Override  
  21.     public void run() {  
  22.         Socket socket = client.socket;  
  23.           
  24.         // 循环检测输入流有没有数据传入,有则显示出来  
  25.         while(true)  
  26.         {  
  27.               
  28.                 try {  
  29.                     BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  30.                     if(reader.ready())  
  31.                     {  
  32.                         String info = reader.readLine();  
  33.                         SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  34.                           
  35.                         client.outputArea.append("Server "+socket.getPort() +" at " + f.format(new Date()) + "\n");  
  36.                         client.outputArea.append("  "+info +"\n");  
  37.                     }  
  38.                       
  39.                 } catch (IOException e) {  
  40.                     e.printStackTrace();  
  41.                 }  
  42.         }  
  43.     }  
  44.       
  45.     //设置发送按钮监听,事件相应  
  46.     @Override  
  47.     public void actionPerformed(ActionEvent e) {  
  48.         String temp = client.inputArea.getText();  
  49.         SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  50.         client.outputArea.append("Client "+client.socket.getLocalPort() +" at " + f.format(new Date()) + "\n");  
  51.         client.outputArea.append("  " + temp + "\n");  
  52.         this.sendInfo(temp);  
  53.         client.inputArea.setText("");  
  54.   
  55.     }  
  56.   
  57.     private void sendInfo(String s) {  
  58.         try {  
  59.             PrintWriter pw = new PrintWriter(client.socket.getOutputStream(),  
  60.                     true);  
  61.             pw.println(s);  
  62.         } catch (IOException e) {  
  63.             e.printStackTrace();  
  64.         }  
  65.     }  
  66.   
  67. }  


执行结果:

 截图1:

Java Socket编程

截图2:

 Java Socket编程

 

1.简述:

Java Socket编程时对于TCP/IP 协议层的通信进行封装,简化了相关的一些操作。//待续

2.Socket 通信时序图

 Java Socket编程

  3.Socket 数据流的交互

Java Socket编程

 

4.单客户端和服务器通信的简单例子:

服务器端代码:

[java] view plain copy
  1. package com.lou.socket;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStreamReader;  
  6. import java.io.PrintWriter;  
  7. import java.net.InetSocketAddress;  
  8. import java.net.ServerSocket;  
  9. import java.net.Socket;  
  10.   
  11. public class TestServer {  
  12. public static void main(String[] args) throws IOException {  
  13.     //1.创建一个Server Socket  
  14.     ServerSocket server = new ServerSocket();  
  15.     // 2.绑定监听指定的端口  
  16.     InetSocketAddress address = new InetSocketAddress("localhost",18824);  
  17.     server.bind(address);  
  18.     // 3.接受此端口的通信请求  
  19.     Socket socket = server.accept();  
  20.     // 在没有客户端对其进行相应前,下面的代码不会执行,将一直阻塞  
  21.       
  22.     //服务器端的输出流和输入流获取  
  23.     BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  24.     PrintWriter writer = new PrintWriter(socket.getOutputStream(),true);  
  25.       
  26.     //来自键盘的输入数据  
  27.     BufferedReader keyword=new BufferedReader(new InputStreamReader(System.in));  
  28.       
  29.     while(true)  
  30.     {  
  31.         if(reader.ready())  
  32.         {  
  33.             // 捕捉来自客户端发来的消息     客户端没有发消息过来时,reader.ready() 为false, 循环检测是否有数据,有测打印出来  
  34.             String info = reader.readLine();  
  35.             System.out.println("Client:"+info);  
  36.         }  
  37.         if(keyword.ready())  
  38.         {  
  39.             //捕获来自服务器端另外一个输入流 : 键盘的数据。如果有数据,则发送给客户端  
  40.             String  test = keyword.readLine();  
  41.             writer.println(test);  
  42.             System.out.println("Server:"+test);  
  43.         }  
  44.           
  45.     }  
  46. }  
  47. }  


客户端代码:

[java] view plain copy
  1. import java.io.BufferedReader;  
  2. import java.io.IOException;  
  3. import java.io.InputStreamReader;  
  4. import java.io.PrintWriter;  
  5. import java.net.InetSocketAddress;  
  6. import java.net.Socket;  
  7. import java.net.UnknownHostException;  
  8.   
  9.   
  10. public class ClientSocket {  
  11.   
  12.     public static void main(String[] args) throws UnknownHostException, IOException {  
  13.           
  14.         //1.创建一个Server Socket  
  15.         Socket socket = new Socket();  
  16.           
  17.         // 2.连接到指定的 server socket,指定IP 和端口号  
  18.         InetSocketAddress address = new InetSocketAddress("localhost",18824);  
  19.         socket.connect(address);  
  20.           
  21.         // 3.连接成功后,获取相应的输入输出流,进行数据交互  
  22.         BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  23.         PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);  
  24.           
  25.         BufferedReader keyword=new BufferedReader(new InputStreamReader(System.in));  
  26.           
  27.         while(true)  
  28.         {  
  29.             // 捕捉来自服务器端发来的消息   服务器端没有发消息过来时,br.ready() 为false, 循环检测是否有数据,有测打印出来  
  30.             if(br.ready())  
  31.             {  
  32.                 String info = br.readLine();  
  33.                 System.out.println("Server:"+info);  
  34.             }  
  35.               
  36.             //捕获来自服务器端另外一个输入流 : 键盘的数据。如果有数据,则发送给服务器端  
  37.             if(keyword.ready())  
  38.             {  
  39.                 String  test = keyword.readLine();  
  40.                 pw.println(test);  
  41.                 System.out.println("Client:"+test);  
  42.             }  
  43.               
  44.         }  
  45.           
  46.   
  47.     }  
  48.   
  49. }  


 运行结果:

 Java Socket编程Java Socket编程

       

5.Socket 多客户端单服务器之间的通信:

       上面的这个例子只能支持一个服务器端和一个客户端的通信,因为 客户端内 server.accept() 方法只执行了一次,只能返回一个Socket 连接。可以在服务端接受多个Socket,这时候的Socket应当放在一个线程里,让它有生命周期,来使用客户端和服务端的*通信。

 

[java] view plain copy
  1. package com.lou.socket;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.InetSocketAddress;  
  5. import java.net.ServerSocket;  
  6. import java.net.Socket;  
  7.   
  8. public class TestServer {  
  9. public static void main(String[] args) throws IOException {  
  10.     //1.创建一个Server Socket  
  11.     ServerSocket server = new ServerSocket();  
  12.     // 2.绑定监听指定的端口  
  13.     InetSocketAddress address = new InetSocketAddress("localhost",18824);  
  14.     server.bind(address);  
  15.     // 3.接受此端口的通信请求  
  16.       
  17.     while(true)  
  18.     {  
  19.         //循环调用accept方法,返回相应的Socket  
  20.         Socket socket = server.accept();  
  21.         //使用线程,将每一个Socket都封装到线程内,这个每个接受的Socket可以*的跟服务器通信了  
  22.         new Thread(new SocketHandler(socket)).start();  
  23.     }  
  24.   
  25. }  
  26. }  


 

[java] view plain copy
  1. package com.lou.socket;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStreamReader;  
  6. import java.io.PrintWriter;  
  7. import java.net.Socket;  
  8.   
  9. public class SocketHandler implements Runnable {  
  10.   
  11.     private Socket socket;  
  12.       
  13.     public SocketHandler(Socket socket)  
  14.     {  
  15.         this.socket =socket;  
  16.     }  
  17.     @Override  
  18.     public void run() {  
  19.         try {  
  20.             BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  21.             PrintWriter writer = new PrintWriter(socket.getOutputStream(),true);  
  22.             //来自键盘的输入数据  
  23.             BufferedReader keyword=new BufferedReader(new InputStreamReader(System.in));  
  24.             boolean flag = true;  
  25.               
  26.             while(flag)  
  27.             {  
  28.                 if(reader.ready())  
  29.                 {  
  30.                     // 捕捉来自客户端发来的消息     客户端没有发消息过来时,reader.ready() 为false, 循环检测是否有数据,有测打印出来  
  31.                     String info = reader.readLine();  
  32.                     System.out.println("Client "+socket.getPort() +":"+info);  
  33.                       
  34.                     //如果对方输入BYE,关闭回话  
  35.                     if("BYE" == info)  
  36.                     {  
  37.                         socket.close();  
  38.                         flag = false;  
  39.                     }  
  40.                 }  
  41.                 if(keyword.ready())  
  42.                 {  
  43.                     //捕获来自服务器端另外一个输入流 : 键盘的数据。如果有数据,则发送给客户端  
  44.                     String  test = keyword.readLine();  
  45.                     writer.println(test);  
  46.                     System.out.println("Server:"+test);  
  47.                       
  48.                       
  49.                 }  
  50.                   
  51.             }  
  52.               
  53.         } catch (IOException e) {  
  54.             e.printStackTrace();  
  55.         }  
  56.   
  57.     }  
  58.   
  59. }  


 

[java] view plain copy
  1. import java.io.BufferedReader;  
  2. import java.io.IOException;  
  3. import java.io.InputStreamReader;  
  4. import java.io.PrintWriter;  
  5. import java.net.InetSocketAddress;  
  6. import java.net.Socket;  
  7. import java.net.UnknownHostException;  
  8.   
  9.   
  10. public class ClientSocket {  
  11.   
  12.     public static void main(String[] args) throws UnknownHostException, IOException {  
  13.           
  14.         //1.创建一个Server Socket  
  15.         Socket socket = new Socket();  
  16.           
  17.         // 2.连接到指定的 server socket,指定IP 和端口号  
  18.         InetSocketAddress address = new InetSocketAddress("localhost",18824);  
  19.         socket.connect(address);  
  20.           
  21.         // 3.连接成功后,获取相应的输入输出流,进行数据交互  
  22.         BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  23.         PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);  
  24.           
  25.         BufferedReader keyword=new BufferedReader(new InputStreamReader(System.in));  
  26.           
  27.         while(true)  
  28.         {  
  29.             // 捕捉来自服务器端发来的消息   服务器端没有发消息过来时,br.ready() 为false, 循环检测是否有数据,有测打印出来  
  30.             if(br.ready())  
  31.             {  
  32.                 String info = br.readLine();  
  33.                 System.out.println("Server:"+info);  
  34.             }  
  35.               
  36.             //捕获来自服务器端另外一个输入流 : 键盘的数据。如果有数据,则发送给服务器端  
  37.             if(keyword.ready())  
  38.             {  
  39.                 String  test = keyword.readLine();  
  40.                 if("BYE" == test)  
  41.                 {  
  42.                     br.close();  
  43.                     pw.close();  
  44.                     socket.close();  
  45.                 }  
  46.                 pw.println(test);  
  47.                 System.out.println("Client:"+test);  
  48.             }  
  49.               
  50.         }  
  51.           
  52.   
  53.     }  
  54.   
  55. }  


 Java Socket编程

 

6. 简易聊天工具的实现:

    实现的主要思路:

   a.在服务器端设置一个主线程,监听特定的一个接口,为每一个socket请求创建一个对话框和相应的处理。

   主线程MainThread代码:

[java] view plain copy
  1. package com.lou.socket;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.InetSocketAddress;  
  5. import java.net.ServerSocket;  
  6. import java.net.Socket;  
  7. import java.util.ArrayList;  
  8. import java.util.List;  
  9.   
  10. /* 
  11.  * server的主线程,监听socket端口,为每一个Socket 创建一个对话框 
  12.  */  
  13. public class MainThread extends Thread{  
  14.       
  15.     public List<Socket> sockets = new ArrayList<Socket>();  
  16.     @Override  
  17.     public void run() {  
  18.         //1.创建一个Server Socket  
  19.         ServerSocket server =null;  
  20.         try {  
  21.             server = new ServerSocket();  
  22.             InetSocketAddress address = new InetSocketAddress("localhost",18824);  
  23.             server.bind(address);  
  24.             while(true)  
  25.             {  
  26.                   
  27.                 //循环调用accept方法,返回相应的Socket  
  28.                 Socket socket = server.accept();  
  29.                 sockets.add(socket);  
  30.                   
  31.                 // 为每一个请求的Socket提供 界面 "会话"  
  32.                 ServerGUI serverGUI = new ServerGUI(socket);  
  33.                 //创建监听socket 数据流输入信息,有数据输入,则更新到GUI  
  34.                 new Thread(new SocketInfoUpdater(serverGUI)).start();  
  35.             }  
  36.               
  37.         } catch (IOException e) {  
  38.             // TODO Auto-generated catch block  
  39.             e.printStackTrace();  
  40.         }  
  41.           
  42.     }  
  43.   
  44.     public static void main(String[] args) {  
  45.   
  46.         new MainThread().start();  
  47.     }  
  48.   
  49. }  


b.定义一个监听线程,用来处理 socket发送过来的数据信息,及时更新到GUI上,和 server GUI 上的发送按钮的事件相应,来发送数据。

事件和输入流监听线程SocketInfoUpdater.java

[java] view plain copy
  1. package com.lou.socket;  
  2.   
  3. import java.awt.event.ActionEvent;  
  4. import java.awt.event.ActionListener;  
  5. import java.io.BufferedReader;  
  6. import java.io.IOException;  
  7. import java.io.InputStreamReader;  
  8. import java.io.PrintWriter;  
  9. import java.net.Socket;  
  10. import java.text.SimpleDateFormat;  
  11. import java.util.Date;  
  12.   
  13. /* 
  14.  * 此线程监听serverGUI所拥有的socket是否有数据输入,如果有更新,则更新到GUI上 
  15.  */  
  16. public class SocketInfoUpdater implements Runnable,ActionListener{  
  17.   
  18.     ServerGUI server;  
  19.       
  20.     SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  21.     public SocketInfoUpdater(ServerGUI server)  
  22.     {  
  23.         this.server = server;  
  24.     }  
  25.     @Override  
  26.     public void run() {  
  27.         Socket socket = server.socket;  
  28.         while(true)  
  29.         {  
  30.                 try {  
  31.                     BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  32.                     if(reader.ready())  
  33.                     {  
  34.                         String info = reader.readLine();  
  35.                         server.outputArea.append("Client-" +socket.getPort()+" at " + f.format(new Date()) + "\n");  
  36.                         server.outputArea.append("  "+info +"\n");  
  37.                     }  
  38.                       
  39.                 } catch (IOException e) {  
  40.                     e.printStackTrace();  
  41.                 }  
  42.                   
  43.         }  
  44.     }  
  45.       
  46.     //设置发送按钮监听,事件相应  
  47.     @Override  
  48.     public void actionPerformed(ActionEvent e) {  
  49.         String temp = server.inputArea.getText();  
  50.         SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  51.         server.outputArea.append("Client "+server.socket.getLocalPort() +" at " + f.format(new Date()) + "\n");  
  52.         server.outputArea.append("  " + temp + "\n");  
  53.         this.sendInfo(temp);  
  54.         server.inputArea.setText("");  
  55.   
  56.     }  
  57.   
  58.     private void sendInfo(String s) {  
  59.         try {  
  60.             PrintWriter pw = new PrintWriter(server.socket.getOutputStream(),  
  61.                     true);  
  62.             pw.println(s);  
  63.         } catch (IOException e) {  
  64.             e.printStackTrace();  
  65.         }  
  66.     }  
  67. }  

 

c. 服务器端界面的设计:

 

 Java Socket编程

服务器端界面设计 ServerGUI.java:

[java] view plain copy
  1. package com.lou.socket;  
  2.   
  3. import java.awt.BorderLayout;  
  4. import java.awt.Container;  
  5. import java.awt.GridLayout;  
  6. import java.io.IOException;  
  7. import java.net.Socket;  
  8.   
  9. import javax.swing.JButton;  
  10. import javax.swing.JFrame;  
  11. import javax.swing.JPanel;  
  12. import javax.swing.JScrollPane;  
  13. import javax.swing.JTextArea;  
  14.   
  15. public class ServerGUI extends JFrame {  
  16.   
  17.     public final Socket socket;  
  18.     //交互对话框中接收数据显示区  
  19.     final JTextArea outputArea = new JTextArea(7070);  
  20.     //输入区域  
  21.     final JTextArea inputArea = new JTextArea(7070);  
  22.     final JScrollPane outputScroll = new JScrollPane(outputArea);  
  23.     final JScrollPane inputScroll = new JScrollPane(inputArea);  
  24.   
  25.     public ServerGUI(Socket socket1) throws IOException {  
  26.           
  27.         //传入特定的socket  
  28.         this.socket = socket1;  
  29.         this.setTitle("Server");  
  30.         Container container = getContentPane();  
  31.         JPanel pane = new JPanel();  
  32.         container.setLayout(new BorderLayout());  
  33.         pane.setLayout(new GridLayout(2155));  
  34.   
  35.         inputScroll.setAutoscrolls(true);  
  36.         outputScroll.setAutoscrolls(true);  
  37.         pane.add(outputScroll);  
  38.   
  39.         pane.add(inputScroll);  
  40.   
  41.         setSize(300300);  
  42.         container.add(pane, BorderLayout.CENTER);  
  43.           
  44.         JButton send = new JButton("Send");  
  45.         //为发送按钮设置发送事件  
  46.         SocketInfoUpdater updater = new SocketInfoUpdater(this);  
  47.         send.addActionListener(updater);  
  48.         container.add(send, BorderLayout.SOUTH);  
  49.         setDefaultCloseOperation(3);  
  50.         setVisible(true);  
  51.     }  
  52. }  


 

客户端的设计:

客户端的实现比较简单,创建一个界面,然后配一个监听输入流和处理事件的监听线程就可以了。

Java Socket编程

a.客户端GUI,ClientGUI代码:

[java] view plain copy
  1. import java.awt.BorderLayout;  
  2. import java.awt.Container;  
  3. import java.awt.GridLayout;  
  4. import java.io.IOException;  
  5. import java.net.InetSocketAddress;  
  6. import java.net.Socket;  
  7.   
  8. import javax.swing.JButton;  
  9. import javax.swing.JFrame;  
  10. import javax.swing.JPanel;  
  11. import javax.swing.JScrollPane;  
  12. import javax.swing.JTextArea;  
  13.   
  14. public class ClientGUI extends JFrame {  
  15.   
  16.     Socket socket = null;  
  17.     final JTextArea outputArea = new JTextArea(7070);  
  18.     final JTextArea inputArea = new JTextArea(7070);  
  19.     final JScrollPane outputScroll = new JScrollPane(outputArea);  
  20.     final JScrollPane inputScroll = new JScrollPane(inputArea);  
  21.   
  22.     public ClientGUI() throws IOException {  
  23.   
  24.         this.setTitle("Client");  
  25.         this.initClientSocket();  
  26.         SocketInfoUpdater updater = new SocketInfoUpdater(this);  
  27.         new Thread(updater).start();  
  28.         Container container = getContentPane();  
  29.         JPanel pane = new JPanel();  
  30.         container.setLayout(new BorderLayout());  
  31.         pane.setLayout(new GridLayout(2155));  
  32.   
  33.         inputScroll.setAutoscrolls(true);  
  34.         outputScroll.setAutoscrolls(true);  
  35.         pane.add(outputScroll);  
  36.   
  37.         pane.add(inputScroll);  
  38.   
  39.         setSize(300300);  
  40.         container.add(pane, BorderLayout.CENTER);  
  41.         JButton send = new JButton("Send");  
  42.         send.addActionListener(updater);  
  43.         container.add(send, BorderLayout.SOUTH);  
  44.   
  45.         setDefaultCloseOperation(3);  
  46.   
  47.         setVisible(true);  
  48.   
  49.   
  50.     }  
  51.   
  52.     /* 
  53.      * 初始化socket 
  54.      */  
  55.     private void initClientSocket() {  
  56.         // 1.创建一个Server Socket  
  57.         socket = new Socket();  
  58.   
  59.         // 2.连接到指定的 server socket,指定IP 和端口号  
  60.         InetSocketAddress address = new InetSocketAddress("localhost"18824);  
  61.         try {  
  62.             socket.connect(address);  
  63.         } catch (IOException e) {  
  64.             e.printStackTrace();  
  65.         }  
  66.     }  
  67.   
  68.     public static void main(String[] args) throws IOException {  
  69.         new ClientGUI();  
  70.   
  71.     }  
  72.   
  73. }  


b. 输入流监听和发送数据的监听线程SocketInfoUpdater.java (这个类其实和服务器端上的基本上一样,之所以把它贴出来是考虑到在后续的开发设计中,Server 端和Client端的机制有所不同):

[java] view plain copy
  1. import java.awt.event.ActionEvent;  
  2. import java.awt.event.ActionListener;  
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStreamReader;  
  6. import java.io.PrintWriter;  
  7. import java.net.Socket;  
  8. import java.text.SimpleDateFormat;  
  9. import java.util.Date;  
  10.   
  11. public class SocketInfoUpdater implements Runnable ,ActionListener{  
  12.   
  13.     ClientGUI client;  
  14.     public SocketInfoUpdater(ClientGUI client)  
  15.     {  
  16.         this.client = client;  
  17.     }  
  18.       
  19.       
  20.     @Override  
  21.     public void run() {  
  22.         Socket socket = client.socket;  
  23.           
  24.         // 循环检测输入流有没有数据传入,有则显示出来  
  25.         while(true)  
  26.         {  
  27.               
  28.                 try {  
  29.                     BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  30.                     if(reader.ready())  
  31.                     {  
  32.                         String info = reader.readLine();  
  33.                         SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  34.                           
  35.                         client.outputArea.append("Server "+socket.getPort() +" at " + f.format(new Date()) + "\n");  
  36.                         client.outputArea.append("  "+info +"\n");  
  37.                     }  
  38.                       
  39.                 } catch (IOException e) {  
  40.                     e.printStackTrace();  
  41.                 }  
  42.         }  
  43.     }  
  44.       
  45.     //设置发送按钮监听,事件相应  
  46.     @Override  
  47.     public void actionPerformed(ActionEvent e) {  
  48.         String temp = client.inputArea.getText();  
  49.         SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  50.         client.outputArea.append("Client "+client.socket.getLocalPort() +" at " + f.format(new Date()) + "\n");  
  51.         client.outputArea.append("  " + temp + "\n");  
  52.         this.sendInfo(temp);  
  53.         client.inputArea.setText("");  
  54.   
  55.     }  
  56.   
  57.     private void sendInfo(String s) {  
  58.         try {  
  59.             PrintWriter pw = new PrintWriter(client.socket.getOutputStream(),  
  60.                     true);  
  61.             pw.println(s);  
  62.         } catch (IOException e) {  
  63.             e.printStackTrace();  
  64.         }  
  65.     }  
  66.   
  67. }  


执行结果:

 截图1:

Java Socket编程

截图2:

 Java Socket编程