TCP和UDP学习总结

总结

TCP

TCP:客户端和服务端连接用socket套接字,传输数据时,用输出流输出(OutputStream)。


传输字符串

客户端

public class TcpClientDemo1 {
   public static void main(String[] args) {
       OutputStream outputStream = null;
       try {
           //1、要知道服务端的地址
           InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
           int port = 9999;
           //创建一个socket连接
           Socket socket = new Socket(inetAddress,port);
           //发送消息
           outputStream = socket.getOutputStream();
           outputStream.write("欢迎学习".getBytes());
           outputStream.flush();

      } catch (Exception e) {
           e.printStackTrace();
      }finally {
           if (outputStream != null) {
               try {
                   outputStream.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
      }



  }
}

服务端

public class TcpServerDemo1 {
   public static void main(String[] args) {
       //1、服务端需要一个地址
       ServerSocket serverSocket = null;
       InputStream inputStream = null;
       Socket socket = null;
       ByteArrayOutputStream byteArrayOutputStream = null;

       try {
           serverSocket = new ServerSocket(9999);
           //接收
           socket = serverSocket.accept();
           //读取客户端的消息
           inputStream = socket.getInputStream();

//           byte[] bytes = new byte[1024];
//           int len;
//           while ((len = inputStream.read(bytes)) != -1){
//               System.out.println(new String(bytes,0,len));
//           }
           //管道流
           byteArrayOutputStream = new ByteArrayOutputStream();
           byte[] bytes = new byte[1024];
           int len;
           while ((len=inputStream.read(bytes))!= -1){
               byteArrayOutputStream.write(bytes,0,len);
          }
           System.out.println(byteArrayOutputStream.toString());

      } catch (IOException e) {
           e.printStackTrace();
      }finally {
           if (byteArrayOutputStream != null) {
               try {
                   byteArrayOutputStream.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if (inputStream != null) {
               try {
                   inputStream.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if (socket != null) {
               try {
                   socket.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }

          }
           if (serverSocket != null) {
               try {
                   serverSocket.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }

      }
  }
}

传输文件

客户端

public class TcpClientDemo02 {
   public static void main(String[] args) throws Exception {
       //上传文件,用Socket连接
       //Socket连接需要传服务端的IP和端口
       Socket socket = new Socket(InetAddress.getByName("localhost"),8888);
//       DatagramSocket socket = new DatagramSocket(8888); //自己端口号位8888

       //将数据打包成一个包裹
       byte[] bytes = new byte[1024];
       //上传一个文件,将文件读出来
       FileInputStream fis = new FileInputStream("网络编程/meitu.jpg");//使用相对路径
       //IO流的老一套
       int len;
       //上传文件,不需要打包,直接用输出流
       OutputStream os = socket.getOutputStream();
       while ((len=fis.read(bytes)) != -1){
           os.write(bytes,0,len);
      }
       os.flush();
//
//       DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length);//包裹要求数据必须为byte数组形式,需要服务端的IP还有端口号
//
//       //将数据传送给服务端
//       socket.send();

       fis.close();
       os.close();
       socket.close();
  }
}

服务端

public class TcpServerDemo02 {
   public static void main(String[] args) throws Exception {
       //创建一个端口为8888的socket连接的服务端
       ServerSocket serverSocket = new ServerSocket(8888);

       //监听连接
       Socket socket = serverSocket.accept();

       //创建输入流,接收客户端输出流的数据
       InputStream is = socket.getInputStream();
       //使用管道流来将读出的数据加载到服务端硬盘中
       FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
       //IO流一套
       byte[] bytes = new byte[1024];
       int len;
       while ((len=is.read(bytes))!=-1){
           fos.write(bytes,0,len);
      }

       fos.close();
       is.close();
       socket.close();
       serverSocket.close();

  }
}

小结

1、使用TCP模式,不管是客户端还是服务端,在写数据时都用管道流进行输出。

问题:如何让服务端给客户端发送信息?

 

UDP

多线程实现聊天咨询

聊天对话的传输端

public class TalkClient implements Runnable {
   DatagramSocket socket = null;
   BufferedReader reader = null;

   private String toIP;
   private int fromPort;
   private int toPort;

   public TalkClient( int fromPort, int toPort,String toIP) {
       this.toIP = toIP;
       this.fromPort = fromPort;
       this.toPort = toPort;
       try {
           socket = new DatagramSocket(this.fromPort);
           reader = new BufferedReader(new InputStreamReader(System.in));
      } catch (SocketException e) {
           e.printStackTrace();
      }

  }

   @Override
   public void run() {
       while (true) {

           try {
               String data = reader.readLine();
               byte[] bytes = data.getBytes();

               DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length, new InetSocketAddress(this.toIP,this.toPort));
               //3、发送包
               socket.send(packet);

               if (data.equals("bye")) {
                   break;
              }
          } catch (Exception e) {
               e.printStackTrace();
          }
           socket.close();
      }
  }
}

接收端

public class TalkReceive implements Runnable{
   DatagramSocket socket = null;

   private int port;
   private String msgFrom;

   public TalkReceive(int port,String msgFrom) {
       this.port = port;
       this.msgFrom = msgFrom;

       try {
           socket = new DatagramSocket(port);
      } catch (SocketException e) {
           e.printStackTrace();
      }
  }

   @Override
   public void run() {
       while (true){
           try {
               byte[] container = new byte[1024];
               DatagramPacket packet = new DatagramPacket(container,0,container.length);
               socket.receive(packet);

               byte[] data = packet.getData();
               String s = new String(data,0,packet.getLength());

               System.out.println(this.msgFrom+":"+s);

               if (s.equals("bye")){
                   break;
              }
          } catch (Exception e) {
               e.printStackTrace();
          }
      }
       socket.close();

  }
}

学生

public class TalkStudent {
   public static void main(String[] args) {
       //开启两个线程
       new Thread(new TalkClient(7777,9999,"localhost")).start();
       new Thread(new TalkReceive(8888,"老师")).start();
  }

}

老师

public class TalkTeacher {
   public static void main(String[] args) {
       //开启两个线程
       new Thread(new TalkClient(6666,8888,"localhost")).start();
       new Thread(new TalkReceive(9999,"学生")).start();
  }
}

小结

学生和老师,都同时拥有接收端和发送端,所以要分别为其分配不同的端口号。

posted @ 2020-05-31 10:59  lee的学习博客  阅读(361)  评论(0)    收藏  举报