• Java网络编程之TCP、UDP


    Java网络编程之TCP、UDP

    分类:
           Java网络编程提供了两种协议:TCP(传输控制协议)和UDP(数据报协议)。TCP(Transmission Control Protocol)是一种可靠的传输协议,传输时会采用“三次握手”端的方式建立连接,以保证数据的可靠性和安全性;而UDP(User Datagram Protocol)协议是一种不可靠的传输协议,发送的数据不一定能够接受的到,网上的聊天是工具一般采用的此协议。下面将详细的接受TCP和UDP的使 用以及相应的编码。

    一、TCP网络通信
           Java中使用Socket(套接字)实现TCP。服务器端使用ServerSocket类,客户端使用Socket类实现。
         
           1、ServerSocket类
            其主要有如下的方法:
           

              ServerSocket()   创建非绑定服务器套接字。
              ServerSocket(int port)  创建绑定到特定端口的服务器套接字。
            
              Socket accept()    侦听并接受到此套接字的连接。
               void close()    关闭此套接字
              boolean isClosed()   返回 ServerSocket 的关闭状态。
              InetAddress getInetAddress()    返回此服务器套接字的本地地址。
              void bind(SocketAddress endpoint)   将 ServerSocket 绑定到特定地址(IP 地址和端口号)。
              boolean isBound()   返回 ServerSocket 的绑定状态。
              SocketAddress getLocalSocketAddress()   返回此套接字绑定的端点的地址,如果尚未绑定则返回 null。
            
             服务器端每次运行是都要使用accept()方法等待客户端的连接,此方法执行之后服务器端将进入阻塞状态,知道客户端连接之后程序才继续执行,此方法返回是Socket,代表一个客户端对象。
            
           2、Socket类
           两台机器连接通信的端点。主要使用如下方法:
         
          Socket(String host, int port)  创建一个流套接字并将其连接到指定主机上的指定端口号。
          OutputStream getOutputStream()   返回此套接字的输出流。
          InputStream getInputStream()    返回此套接字的输入流。
          boolean isBound()    返回套接字的绑定状态。
          boolean isClosed()   返回套接字的关闭状态。
          boolean isConnected()     返回套接字的连接状态。
          void close()     关闭此套接字。
         其通过字节流和服务端进行通信。

          实例一、下面是实现一个简单的TCP客户端可服务器端通信。
       (1)服务器端:

    1. package andy.network.test;  
    2.   
    3. import java.io.IOException;  
    4. import java.io.PrintStream;  
    5. import java.net.ServerSocket;  
    6. import java.net.Socket;  
    7.   
    8. /**   
    9.  * @author Zhang,Tianyou   
    10.  * version:2014-11-25 上午10:49:11   
    11.  *  
    12.  *   
    13.  */  
    14.   
    15. public class FirstTCPServer {  
    16.   
    17.     /** 
    18.      * @param args 
    19.      * @throws IOException  
    20.      */  
    21.     public static void main(String[] args) throws IOException {  
    22.         //创建服务器  
    23.         ServerSocket server = null;  
    24.         Socket socket = null;  
    25.         PrintStream out = null;  
    26.         //服务器在9999上等待客户端的访问  
    27.         server = new ServerSocket(9999);  
    28.           
    29.         System.out.println("服务器端已经运行,等待客户的响应。。。");  
    30.         //程序阻塞 等待客户端的访问  
    31.         socket = server.accept();  
    32.         //向客户端输出信息  
    33.         String str = "hello andy.";  
    34.           
    35.         out = new PrintStream(socket.getOutputStream());  
    36.         out.print(str);  
    37.         out.close();  
    38.         socket.close();  
    39.         server.close();  
    40.           
    41.     }  
    42.   
    43. }  


    (2)客户端:

    1. package andy.network.test;  
    2.   
    3. import java.io.BufferedReader;  
    4. import java.io.IOException;  
    5. import java.io.InputStreamReader;  
    6. import java.net.Socket;  
    7. import java.net.UnknownHostException;  
    8.   
    9. /** 
    10.  * @author Zhang,Tianyou  
    11.  * version:2014-11-25 上午11:02:17 
    12.  *  
    13.  *  
    14.  */  
    15.   
    16. public class FirstTCPSocket {  
    17.   
    18.     /** 
    19.      * @param args 
    20.      * @throws IOException 
    21.      * @throws UnknownHostException 
    22.      */  
    23.     public static void main(String[] args) throws UnknownHostException,  
    24.             IOException {  
    25.         // 定义客户端  
    26.         Socket client = null;  
    27.         // 设置地址和端口  
    28.         client = new Socket("localhost", 9999);  
    29.   
    30.         BufferedReader buf = null; // 结束服务端流  
    31.         buf = new BufferedReader(new InputStreamReader(client.getInputStream()));  
    32.         String str = buf.readLine();  
    33.         System.out.println("服务器端通知信息:" + str);  
    34.         buf.close();  
    35.         client.close();  
    36.   
    37.     }  
    38.   
    39. }  


       实例二
       实现客户端和服务器端的通信,服务器端可以响应多个客户端,每个客户端请求就启动一个线程。

        (1)服务端
     

    1. package andy.network.test;  
    2.   
    3. import java.io.IOException;  
    4. import java.net.ServerSocket;  
    5. import java.net.Socket;  
    6.   
    7. /** 
    8.  * @author Zhang,Tianyou  
    9.  * version:2014-11-25 上午11:41:22 
    10.  *  
    11.  *         聊天服务器端 
    12.  */  
    13.   
    14. public class ChatServer {  
    15.   
    16.     /** 
    17.      * @param args 
    18.      * @throws IOException 
    19.      */  
    20.     public static void main(String[] args) throws IOException {  
    21.   
    22.         ServerSocket server = null;  
    23.         Socket client = null;  
    24.         // 监听9999端口的连接  
    25.         server = new ServerSocket(9999);  
    26.         boolean  flag = true;  
    27.         while (flag) {  
    28.             System.out.println("服务器运行,等待客户端连接。");  
    29.             client = server.accept();  
    30.             // 对每一个客户端请求启动一个线程  
    31.             new Thread(new ChatThread(client)).start();  
    32.   
    33.         }  
    34.           
    35.         server.close();  
    36.   
    37.     }  
    38.   
    39. }  


     对应服务端线程任务:
     

    1. package andy.network.test;  
    2.   
    3. import java.io.BufferedReader;  
    4. import java.io.InputStreamReader;  
    5. import java.io.PrintStream;  
    6. import java.net.Socket;  
    7.   
    8. /** 
    9.  * @author Zhang,Tianyou  
    10.  * version:2014-11-25 上午11:24:26 
    11.  *  
    12.  *         使用多线程机制,在每个用户响应之后启动一个新任务 
    13.  *  
    14.  */  
    15.   
    16. public class ChatThread implements Runnable {  
    17.   
    18.     // 接受客户端  
    19.     private Socket client = null;  
    20.   
    21.     public ChatThread(Socket client) {  
    22.         this.client = client;  
    23.     }  
    24.   
    25.     @Override  
    26.     public void run() {  
    27.         // 向客户端发送数据  
    28.         PrintStream out = null;  
    29.         // 接收客户端发来的数据  
    30.         BufferedReader buff = null;  
    31.         try {  
    32.             // 得到客户端的输入信息  
    33.             buff = new BufferedReader(new InputStreamReader(  
    34.                     client.getInputStream()));  
    35.             out = new PrintStream(client.getOutputStream());  
    36.             //标志是否一个客户端的操作完毕  
    37.             boolean flag = true;  
    38.               
    39.             while (flag) {  
    40.                 //不断的接收信息  
    41.                 String str = buff.readLine();  
    42.                 if(str == null || "".equals(str)){  
    43.                     flag = false;//客户端操作结束  
    44.                 }else{  
    45.                     if("bye".equals(str)){  
    46.                         flag = false;  
    47.                         out.println("bye-bye");   
    48.                     }else {  
    49.                         //向客户端回显输入  
    50.                         out.println("you input:" + str);  
    51.                     }  
    52.                 }  
    53.             }  
    54.               
    55.             out.close();  
    56.             client.close();  
    57.   
    58.         } catch (Exception e) {  
    59.             System.out.println("服务器异常!");   
    60.         }  
    61.   
    62.     }  
    63.   
    64. }  


    (2)客户端

    1. package andy.network.test;  
    2.   
    3. import java.io.BufferedReader;  
    4. import java.io.IOException;  
    5. import java.io.InputStreamReader;  
    6. import java.io.PrintStream;  
    7. import java.net.Socket;  
    8. import java.net.UnknownHostException;  
    9.   
    10. /** 
    11.  * @author Zhang,Tianyou  
    12.  * version:2014-11-25 上午11:53:03 
    13.  *  
    14.  *         聊天客户端程序 
    15.  *  
    16.  */  
    17.   
    18. public class ChatClient {  
    19.   
    20.     public static void main(String[] args) throws UnknownHostException,  
    21.             IOException {  
    22.   
    23.         Socket client = null;  
    24.         client = new Socket("localhost", 9999);  
    25.         // 接收服务器端的信息  
    26.         BufferedReader buff = null;  
    27.         // 向服务器端发送数据  
    28.         PrintStream out = null;  
    29.         BufferedReader input = null;  
    30.         // 获取键盘输入数据  
    31.         input = new BufferedReader(new InputStreamReader(System.in));  
    32.   
    33.         out = new PrintStream(client.getOutputStream());  
    34.   
    35.         buff = new BufferedReader(  
    36.                 new InputStreamReader(client.getInputStream()));  
    37.         // 标志位  
    38.         boolean flag = true;  
    39.         while (flag) {  
    40.             System.out.println("输入信息:");  
    41.             String str = input.readLine();  
    42.             // 向服务器端输出信息  
    43.             out.println(str);  
    44.   
    45.             if ("bye".equals(str)) {  
    46.                 flag = false;  
    47.             } else {  
    48.                 String chatCont = buff.readLine();  
    49.                 System.out.println(chatCont);  
    50.             }  
    51.   
    52.         }  
    53.   
    54.         client.close();  
    55.         buff.close();  
    56.     }  
    57.   
    58. }  


    二、UDP网络通信
       TCP的通信是建立在可靠通信的基础上,UDP则是不可靠的通信,使用数据报形式发送数据。
       在Java中主要有DatagramPacket和DatagramSocket实现。

      1、DatagramPacket主要方法
           DatagramPacket(byte[] buf, int length)
                构造 DatagramPacket,用来接收长度为 length 的数据包。
          DatagramPacket(byte[] buf, int length, InetAddress address, int port)
               构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
          byte[] getData()
                返回数据缓冲区。
         int getLength()
              返回将要发送或接收到的数据的长度。

     2、DatagramSocket主要方法
         DatagramSocket(int port)
                创建数据报套接字并将其绑定到本地主机上的指定端口。
         void receive(DatagramPacket p)
                从此套接字接收数据报包。
         void send(DatagramPacket p)
                从此套接字发送数据报包。
     在使用UDP时,先使用客户端指定好要接受的数据和端口。然后开启服务端发送数据。

    实现如下:
    (1)客户端

    1. package andy.network.test;  
    2.   
    3. import java.io.IOException;  
    4. import java.net.DatagramPacket;  
    5. import java.net.DatagramSocket;  
    6.   
    7. /** 
    8.  * @author Zhang,Tianyou  
    9.  * version:2014-11-25 下午3:04:10 
    10.  *  
    11.  *         UDP客户端 
    12.  */  
    13.   
    14. public class UDPClient {  
    15.   
    16.     /** 
    17.      * @param args 
    18.      * @throws IOException 
    19.      */  
    20.     public static void main(String[] args) throws IOException {  
    21.         // 客户在9999端口监听  
    22.         DatagramSocket dSocket = null;  
    23.         dSocket = new DatagramSocket(9999);  
    24.         // 定义接收数据的字节长度  
    25.         byte[] buff = new byte[1024];  
    26.         DatagramPacket dPacket = null;  
    27.         // 指定接收数据的长度1024  
    28.         dPacket = new DatagramPacket(buff, 1024);  
    29.         System.out.println("等待接受数据。。");  
    30.         //接收数据  
    31.         dSocket.receive(dPacket);  
    32.         String str = new String(dPacket.getData(), 0, dPacket.getLength())  
    33.                 + "from" + dPacket.getAddress().getHostAddress() + ":"  
    34.                 + dPacket.getPort();  
    35.         System.out.println(str);  
    36.         //关闭数据报套接字  
    37.         dSocket.close();  
    38.     }  
    39.   
    40. }  


      (2)服务器端

    1. package andy.network.test;  
    2.   
    3. import java.io.IOException;  
    4. import java.net.DatagramPacket;  
    5. import java.net.DatagramSocket;  
    6. import java.net.InetAddress;  
    7.   
    8. /**   
    9.  * @author Zhang,Tianyou   
    10.  * version:2014-11-25 下午3:13:38   
    11.  *  
    12.  * UDP服务器端 
    13.  *   
    14.  */  
    15.   
    16. public class UDPServer {  
    17.   
    18.     /** 
    19.      * @param args 
    20.      * @throws IOException  
    21.      */  
    22.     public static void main(String[] args) throws IOException {  
    23.         DatagramSocket dSocket = null;  
    24.         //服务端在3333端口监听  
    25.         dSocket = new DatagramSocket(3333);  
    26.         DatagramPacket dPacket = null;  
    27.         //要发生的数据  
    28.         String str = "hello andy!";  
    29.         //向目标端口地址发送数据报  
    30.         dPacket = new DatagramPacket(str.getBytes(), str.length(),  
    31.                 InetAddress.getByName("localhost") , 9999);  
    32.           
    33.         System.out.println("发送数据报");   
    34.           
    35.         dSocket.send(dPacket);  
    36.         dSocket.close();  
    37.   
    38.     }  
    39.   
    40. }  
  • 相关阅读:
    05Linux文件修改
    07Linux基本权限
    09Linux软件安装
    搬家
    web项目和单元测试
    session_start() 对 HTTP_REQUEST扩展/fsockopen函数 的影响
    从不同架构的角度进行web项目的需求分析和系统设计
    程序中的风险控制
    【原创】 书籍推荐
    【转载】10个效果最佳的编程字体
  • 原文地址:https://www.cnblogs.com/lykxqhh/p/5691225.html
Copyright © 2020-2023  润新知