Java网络编程之TCP、UDP

时间:2023-03-09 08:28:07
Java网络编程之TCP、UDP

Java网络编程之TCP、UDP

2014-11-25 15:23 513人阅读 评论(0) 收藏 举报
Java网络编程之TCP、UDP 分类:
java基础及多线程(28) 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. import java.io.IOException;
  3. import java.io.PrintStream;
  4. import java.net.ServerSocket;
  5. import java.net.Socket;
  6. /**
  7. * @author Zhang,Tianyou
  8. * version:2014-11-25 上午10:49:11
  9. *
  10. *
  11. */
  12. public class FirstTCPServer {
  13. /**
  14. * @param args
  15. * @throws IOException
  16. */
  17. public static void main(String[] args) throws IOException {
  18. //创建服务器
  19. ServerSocket server = null;
  20. Socket socket = null;
  21. PrintStream out = null;
  22. //服务器在9999上等待客户端的访问
  23. server = new ServerSocket(9999);
  24. System.out.println("服务器端已经运行,等待客户的响应。。。");
  25. //程序阻塞 等待客户端的访问
  26. socket = server.accept();
  27. //向客户端输出信息
  28. String str = "hello andy.";
  29. out = new PrintStream(socket.getOutputStream());
  30. out.print(str);
  31. out.close();
  32. socket.close();
  33. server.close();
  34. }
  35. }

(2)客户端:

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

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

(1)服务端

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

对应服务端线程任务:

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

(2)客户端

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

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

(2)服务器端

  1. package andy.network.test;
  2. import java.io.IOException;
  3. import java.net.DatagramPacket;
  4. import java.net.DatagramSocket;
  5. import java.net.InetAddress;
  6. /**
  7. * @author Zhang,Tianyou
  8. * version:2014-11-25 下午3:13:38
  9. *
  10. * UDP服务器端
  11. *
  12. */
  13. public class UDPServer {
  14. /**
  15. * @param args
  16. * @throws IOException
  17. */
  18. public static void main(String[] args) throws IOException {
  19. DatagramSocket dSocket = null;
  20. //服务端在3333端口监听
  21. dSocket = new DatagramSocket(3333);
  22. DatagramPacket dPacket = null;
  23. //要发生的数据
  24. String str = "hello andy!";
  25. //向目标端口地址发送数据报
  26. dPacket = new DatagramPacket(str.getBytes(), str.length(),
  27. InetAddress.getByName("localhost") , 9999);
  28. System.out.println("发送数据报");
  29. dSocket.send(dPacket);
  30. dSocket.close();
  31. }
  32. }
Java网络编程之TCP、UDP