网络编程入门-UDP通信程序-TCP通信程序

【JAVA】UDP通信 目录 1.【UDP通信】 1.1【UDP发送数据】 1.2【UDP接收数据】 1.3【UDP通信——示例项目】 2.【UDP的三种通信方式】 2.1【单播】 2.2【组播】 2.2.1【组播地址】 2.2.2【发送端】 2.2.3【接收端】 2.3【广播】 2.3.1【组播地址】 2.3.2【发送端】 2.3.3【接收端】 1.【UDP通信】 1.1【UDP发送数据】 【构造方法】: DatagramSocket():构造一个数据报套接字并将其绑定到本地主机上的任何可.. 阅读详情

1.网络编程入门

1.1 网络编程概述【理解】

  • 计算机网络
    是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统
  • 网络编程
    在网络通信协议下,不同计算机上运行的程序,可以进行数据传输

1.2 网络编程三要素【理解】

  • IP地址
    要想让网络中的计算机能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接收数据的计算机和识别发送的计算机,而IP地址就是这个标识号。也就是设备的标识
  • 端口
    网络的通信,本质上是两个应用程序的通信。每台计算机都有很多的应用程序,那么在网络通信时,如何区分这些应用程序呢?如果说IP地址可以唯一标识网络中的设备,那么端口号就可以唯一标识设备中的应用程序了。也就是应用程序的标识
  • 协议
    通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要遵守一定的规则,这就好比在道路中行驶的汽车一定要遵守交通规则一样。在计算机网络中,这些连接和通信的规则被称为网络通信协议,它对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守才能完成数据交换。常见的协议有UDP协议和TCP协议

1.3 IP地址【理解】

IP地址:是网络中设备的唯一标识

  • IP地址分为两大类
    • IPv4:是给每个连接在网络上的主机分配一个32bit地址。按照TCP/IP规定,IP地址用二进制来表示,每个IP地址长32bit,也就是4个字节。例如一个采用二进制形式的IP地址是“11000000 10101000 00000001 01000010”,这么长的地址,处理起来也太费劲了。为了方便使用,IP地址经常被写成十进制的形式,中间使用符号“.”分隔不同的字节。于是,上面的IP地址可以表示为“192.168.1.66”。IP地址的这种表示法叫做“点分十进制表示法”,这显然比1和0容易记忆得多
    • IPv6:由于互联网的蓬勃发展,IP地址的需求量愈来愈大,但是网络地址资源有限,使得IP的分配越发紧张。为了扩大地址空间,通过IPv6重新定义地址空间,采用128位地址长度,每16个字节一组,分成8组十六进制数,这样就解决了网络地址资源数量不够的问题
  • DOS常用命令:
    • ipconfig:查看本机IP地址
    • ping IP地址:检查网络是否连通
  • 特殊IP地址:
    • 127.0.0.1:是回送地址,可以代表本机地址,一般用来测试使用

1.4 InetAddress【应用】

InetAddress:此类表示Internet协议(IP)地址

  • 相关方法
    方法名 说明
    static InetAddress getByName(String host) 确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址
    String getHostName() 获取此IP地址的主机名
    String getHostAddress() 返回文本显示中的IP地址字符串
  • 代码演示
public class InetAddressDemo {
      public static void main(String[] args) throws UnknownHostException {
  		//InetAddress address = InetAddress.getByName("xxx");
          InetAddress address = InetAddress.getByName("192.168.1.66");
  
          //public String getHostName():获取此IP地址的主机名
          String name = address.getHostName();
          //public String getHostAddress():返回文本显示中的IP地址字符串
          String ip = address.getHostAddress();
  
          System.out.println("主机名:" + name);
          System.out.println("IP地址:" + ip);
      }
  }

1.5 端口和协议【理解】

  • 端口
    • 设备上应用程序的唯一标识
  • 端口号
    • 用两个字节表示的整数,它的取值范围是065535。其中,01023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败
  • 协议
    • 计算机网络中,连接和通信的规则被称为网络通信协议
  • UDP协议
    • 用户数据报协议(User Datagram Protocol)
    • UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
    • 由于使用UDP协议消耗系统资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输
    • 例如视频会议通常采用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议
  • TCP协议
    • 传输控制协议 (Transmission Control Protocol)
    • TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”
    • 三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠
      第一次握手,客户端向服务器端发出连接请求,等待服务器确认
      第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求
      第三次握手,客户端再次向服务器端发送确认信息,确认连接
    • 完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输了。由于这种面向连接的特性,TCP协议可以保证传输数据的安全,所以应用十分广泛。例如上传文件、下载文件、浏览网页等

2.UDP通信程序

2.1 UDP发送数据【应用】

  • Java中的UDP通信
    • UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象,因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器的概念
    • Java提供了DatagramSocket类作为基于UDP协议的Socket
  • 构造方法
    方法名 说明
    DatagramSocket() 创建数据报套接字并将其绑定到本机地址上的任何可用端口
    DatagramPacket(byte[] buf,int len,InetAddress add,int port) 创建数据包,发送长度为len的数据包到指定主机的指定端口
  • 相关方法
    方法名 说明
    void send(DatagramPacket p) 发送数据报包
    void close() 关闭数据报套接字
    void receive(DatagramPacket p) 从此套接字接受数据报包
  • 发送数据的步骤
    • 创建发送端的Socket对象(DatagramSocket)
    • 创建数据,并把数据打包
    • 调用DatagramSocket对象的方法发送数据
    • 关闭发送端
  • 代码演示
public class SendDemo {
      public static void main(String[] args) throws IOException {
          //创建发送端的Socket对象(DatagramSocket)
          // DatagramSocket() 构造数据报套接字并将其绑定到本地主机上的任何可用端口
          DatagramSocket ds = new DatagramSocket();
  
          //创建数据,并把数据打包
          //DatagramPacket(byte[] buf, int length, InetAddress address, int port)
          //构造一个数据包,发送长度为 length的数据包到指定主机上的指定端口号。
          byte[] bys = "hello,udp,我来了".getBytes();
  
          DatagramPacket dp = new DatagramPacket(bys,bys.length,InetAddress.getByName("127.0.0.1"),10086);
  
          //调用DatagramSocket对象的方法发送数据
          //void send(DatagramPacket p) 从此套接字发送数据报包
          ds.send(dp);
  
          //关闭发送端
          //void close() 关闭此数据报套接字
          ds.close();
      }
  }

2.2UDP接收数据【应用】

  • 接收数据的步骤
    • 创建接收端的Socket对象(DatagramSocket)
    • 创建一个数据包,用于接收数据
    • 调用DatagramSocket对象的方法接收数据
    • 解析数据包,并把数据在控制台显示
    • 关闭接收端
  • 构造方法
    方法名 说明
    DatagramPacket(byte[] buf, int len) 创建一个DatagramPacket用于接收长度为len的数据包
  • 相关方法
    方法名 说明
    byte[] getData() 返回数据缓冲区
    int getLength() 返回要发送的数据的长度或接收的数据的长度
  • 示例代码
   public class ReceiveDemo {
          public static void main(String[] args) throws IOException {
            	//创建接收端的Socket对象(DatagramSocket)
            	DatagramSocket ds = new DatagramSocket(12345);
      
            	//创建一个数据包,用于接收数据
            	byte[] bys = new byte[1024];
            	DatagramPacket dp = new DatagramPacket(bys, bys.length);
      
            	//调用DatagramSocket对象的方法接收数据
            	ds.receive(dp);
      
            	//解析数据包,并把数据在控制台显示
            	System.out.println("数据是:" + new String(dp.getData(), 0,                                             dp.getLength()));
              }
          }
      }

2.3UDP通信程序练习【应用】

  • 案例需求
    UDP发送数据:数据来自于键盘录入,直到输入的数据是886,发送数据结束
    UDP接收数据:因为接收端不知道发送端什么时候停止发送,故采用死循环接收
  • 代码实现
/*
      UDP发送数据:
          数据来自于键盘录入,直到输入的数据是886,发送数据结束
   */
  public class SendDemo {
      public static void main(String[] args) throws IOException {
          //创建发送端的Socket对象(DatagramSocket)
          DatagramSocket ds = new DatagramSocket();
          //键盘录入数据
          Scanner sc = new Scanner(System.in);
          while (true) {
            	String s = sc.nextLine();
              //输入的数据是886,发送数据结束
              if ("886".equals(s)) {
                  break;
              }
              //创建数据,并把数据打包
              byte[] bys = s.getBytes();
              DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName("192.168.1.66"), 12345);
  
              //调用DatagramSocket对象的方法发送数据
              ds.send(dp);
          }
          //关闭发送端
          ds.close();
      }
  }
  
  /*
      UDP接收数据:
          因为接收端不知道发送端什么时候停止发送,故采用死循环接收
   */
  public class ReceiveDemo {
      public static void main(String[] args) throws IOException {
          //创建接收端的Socket对象(DatagramSocket)
          DatagramSocket ds = new DatagramSocket(12345);
          while (true) {
              //创建一个数据包,用于接收数据
              byte[] bys = new byte[1024];
              DatagramPacket dp = new DatagramPacket(bys, bys.length);
              //调用DatagramSocket对象的方法接收数据
              ds.receive(dp);
              //解析数据包,并把数据在控制台显示
              System.out.println("数据是:" + new String(dp.getData(), 0, dp.getLength()));
          }
          //关闭接收端
  //        ds.close();
      }
  }

2.4UDP三种通讯方式【理解】

  • 单播
    单播用于两个主机之间的端对端通信
  • 组播
    组播用于对一组特定的主机进行通信
  • 广播
    广播用于一个主机对整个局域网上所有主机上的数据通信

2.5UDP组播实现【理解】

  • 实现步骤
    • 发送端
      1. 创建发送端的Socket对象(DatagramSocket)
      2. 创建数据,并把数据打包(DatagramPacket)
      3. 调用DatagramSocket对象的方法发送数据(在单播中,这里是发给指定IP的电脑但是在组播当中,这里是发给组播地址)
      4. 释放资源
    • 接收端
      1. 创建接收端Socket对象(MulticastSocket)
      2. 创建一个箱子,用于接收数据
      3. 把当前计算机绑定一个组播地址
      4. 将数据接收到箱子中
      5. 解析数据包,并打印数据
      6. 释放资源
  • 代码实现
 // 发送端
  public class ClinetDemo {
      public static void main(String[] args) throws IOException {
          // 1. 创建发送端的Socket对象(DatagramSocket)
          DatagramSocket ds = new DatagramSocket();
          String s = "hello 组播";
          byte[] bytes = s.getBytes();
          InetAddress address = InetAddress.getByName("224.0.1.0");
          int port = 10000;
          // 2. 创建数据,并把数据打包(DatagramPacket)
          DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
          // 3. 调用DatagramSocket对象的方法发送数据(在单播中,这里是发给指定IP的电脑但是在组播当中,这里是发给组播地址)
          ds.send(dp);
          // 4. 释放资源
          ds.close();
      }
  }
  // 接收端
  public class ServerDemo {
      public static void main(String[] args) throws IOException {
          // 1. 创建接收端Socket对象(MulticastSocket)
          MulticastSocket ms = new MulticastSocket(10000);
          // 2. 创建一个箱子,用于接收数据
          DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
          // 3. 把当前计算机绑定一个组播地址,表示添加到这一组中.
          ms.joinGroup(InetAddress.getByName("224.0.1.0"));
          // 4. 将数据接收到箱子中
          ms.receive(dp);
          // 5. 解析数据包,并打印数据
          byte[] data = dp.getData();
          int length = dp.getLength();
          System.out.println(new String(data,0,length));
          // 6. 释放资源
          ms.close();
      }
  }

2.6UDP广播实现【理解】

  • 实现步骤
    • 发送端
      1. 创建发送端Socket对象(DatagramSocket)
      2. 创建存储数据的箱子,将广播地址封装进去
      3. 发送数据
      4. 释放资源
    • 接收端
      1. 创建接收端的Socket对象(DatagramSocket)
      2. 创建一个数据包,用于接收数据
      3. 调用DatagramSocket对象的方法接收数据
      4. 解析数据包,并把数据在控制台显示
      5. 关闭接收端
  • 代码实现
 // 发送端
  public class ClientDemo {
      public static void main(String[] args) throws IOException {
        	// 1. 创建发送端Socket对象(DatagramSocket)
          DatagramSocket ds = new DatagramSocket();
  		// 2. 创建存储数据的箱子,将广播地址封装进去
          String s = "广播 hello";
          byte[] bytes = s.getBytes();
          InetAddress address = InetAddress.getByName("255.255.255.255");
          int port = 10000;
          DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
  		// 3. 发送数据
          ds.send(dp);
  		// 4. 释放资源
          ds.close();
      }
  }
  // 接收端
  public class ServerDemo {
      public static void main(String[] args) throws IOException {
          // 1. 创建接收端的Socket对象(DatagramSocket)
          DatagramSocket ds = new DatagramSocket(10000);
          // 2. 创建一个数据包,用于接收数据
          DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
          // 3. 调用DatagramSocket对象的方法接收数据
          ds.receive(dp);
          // 4. 解析数据包,并把数据在控制台显示
          byte[] data = dp.getData();
          int length = dp.getLength();
          System.out.println(new String(data,0,length));
          // 5. 关闭接收端
          ds.close();
      }
  }

3.TCP通信程序

3.1TCP发送数据【应用】

Java中的TCP通信

  • Java对基于TCP协议的的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信。
  • Java为客户端提供了Socket类,为服务器端提供了ServerSocket类
  • 构造方法
    方法名 说明
    Socket(InetAddress address,int port) 创建流套接字并将其连接到指定IP指定端口号
    Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号
  • 相关方法
    方法名 说明
    InputStream getInputStream() 返回此套接字的输入流
    OutputStream getOutputStream() 返回此套接字的输出流
  • 示例代码
public class ClientDemo {
      public static void main(String[] args) throws IOException {
          //创建客户端的Socket对象(Socket)
          //Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号
          Socket s = new Socket("127.0.0.1",10000);
  
          //获取输出流,写数据
          //OutputStream getOutputStream() 返回此套接字的输出流
          OutputStream os = s.getOutputStream();
          os.write("hello,tcp,我来了".getBytes());
  
          //释放资源
          s.close();
      }
  }

3.2TCP接收数据【应用】

  • 构造方法
    方法名 说明
    ServletSocket(int port) 创建绑定到指定端口的服务器套接字

  • 相关方法
    方法名 说明
    Socket accept() 监听要连接到此的套接字并接受它

  • 注意事项

    1. accept方法是阻塞的,作用就是等待客户端连接
    2. 客户端创建对象并连接服务器,此时是通过三次握手协议,保证跟服务器之间的连接
    3. 针对客户端来讲,是往外写的,所以是输出流
      针对服务器来讲,是往里读的,所以是输入流
    4. read方法也是阻塞的
    5. 客户端在关流的时候,还多了一个往服务器写结束标记的动作
    6. 最后一步断开连接,通过四次挥手协议保证连接终止
  • 三次握手和四次挥手

    • 三次握手
      在这里插入图片描述

    • 四次挥手
      在这里插入图片描述

  • 示例代码

public class ServerDemo {
      public static void main(String[] args) throws IOException {
          //创建服务器端的Socket对象(ServerSocket)
          //ServerSocket(int port) 创建绑定到指定端口的服务器套接字
          ServerSocket ss = new ServerSocket(10000);
  
          //Socket accept() 侦听要连接到此套接字并接受它
          Socket s = ss.accept();
  
          //获取输入流,读数据,并把数据显示在控制台
          InputStream is = s.getInputStream();
          byte[] bys = new byte[1024];
          int len = is.read(bys);
          String data = new String(bys,0,len);
          System.out.println("数据是:" + data);
  
          //释放资源
          s.close();
          ss.close();
      }
  }

3.3TCP程序练习【应用】

  • 案例需求
    客户端:发送数据,接受服务器反馈
    服务器:收到消息后给出反馈
  • 案例分析
    • 客户端创建对象,使用输出流输出数据
    • 服务端创建对象,使用输入流接受数据
    • 服务端使用输出流给出反馈数据
    • 客户端使用输入流接受反馈数据
  • 代码实现
  // 客户端
  public class ClientDemo {
      public static void main(String[] args) throws IOException {
          Socket socket = new Socket("127.0.0.1",10000);
  
          OutputStream os = socket.getOutputStream();
          os.write("hello".getBytes());
         // os.close();如果在这里关流,会导致整个socket都无法使用
          socket.shutdownOutput();//仅仅关闭输出流.并写一个结束标记,对socket没有任何影响
          
          BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
          String line;
          while((line = br.readLine())!=null){
              System.out.println(line);
          }
          br.close();
          os.close();
          socket.close();
      }
  }
  // 服务器
  public class ServerDemo {
      public static void main(String[] args) throws IOException {
          ServerSocket ss = new ServerSocket(10000);
  
          Socket accept = ss.accept();
  
          InputStream is = accept.getInputStream();
          int b;
          while((b = is.read())!=-1){
              System.out.println((char) b);
          }
  
          System.out.println("看看我执行了吗?");
  
          BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
          bw.write("你谁啊?");
          bw.newLine();
          bw.flush();
  
          bw.close();
          is.close();
          accept.close();
          ss.close();
      }
  }

3.4TCP程序文件上传练习【应用】

  • 案例需求
    客户端:数据来自于本地文件,接收服务器反馈
    服务器:接收到的数据写入本地文件,给出反馈
  • 案例分析
    • 创建客户端对象,创建输入流对象指向文件,每读一次数据就给服务器输出一次数据,输出结束后使用shutdownOutput()方法告知服务端传输结束
    • 创建服务器对象,创建输出流对象指向文件,每接受一次数据就使用输出流输出到文件中,传输结束后。使用输出流给客户端反馈信息
    • 客户端接受服务端的回馈信息
  • 相关方法
    方法名 说明
    void shutdownInput() 将此套接字的输入流放置在“流的末尾”
    void shutdownOutput() 禁止用此套接字的输出流
  • 代码实现
 // 客户端
  public class ClientDemo {
      public static void main(String[] args) throws IOException {
          Socket socket = new Socket("127.0.0.1",10000);
  
          //是本地的流,用来读取本地文件的.
          BufferedInputStream bis = new BufferedInputStream(new FileInputStream("socketmodule\\ClientDir\\1.jpg"));
  
          //写到服务器 --- 网络中的流
          OutputStream os = socket.getOutputStream();
          BufferedOutputStream bos = new BufferedOutputStream(os);
  
          int b;
          while((b = bis.read())!=-1){
              bos.write(b);//通过网络写到服务器中
          }
          bos.flush();
          //给服务器一个结束标记,告诉服务器文件已经传输完毕
          socket.shutdownOutput();
  
          BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
          String line;
          while((line = br.readLine()) !=null){
              System.out.println(line);
          }
          bis.close();
          socket.close();
      }
  }
  // 服务器
  public class ServerDemo {
      public static void main(String[] args) throws IOException {
          ServerSocket ss = new ServerSocket(10000);
  
          Socket accept = ss.accept();
  
          //网络中的流,从客户端读取数据的
          BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
          //本地的IO流,把数据写到本地中,实现永久化存储
          BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("socketmodule\\ServerDir\\copy.jpg"));
  
          int b;
          while((b = bis.read()) !=-1){
              bos.write(b);
          }
  
          BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
          bw.write("上传成功");
          bw.newLine();
          bw.flush();
  
          bos.close();
          accept.close();
          ss.close();
      }
  }

3.5TCP程序服务器优化【应用】

- 优化方案一

  • 需求
    服务器只能处理一个客户端请求,接收完一个图片之后,服务器就关闭了。
  • 解决方案
    使用循环
  • 代码实现
    // 服务器代码如下,客户端代码同上个案例,此处不再给出
       public class ServerDemo {
           public static void main(String[] args) throws IOException {
               ServerSocket ss = new ServerSocket(10000);
       
               while (true) {
                   Socket accept = ss.accept();
       
                   //网络中的流,从客户端读取数据的
                   BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
                   //本地的IO流,把数据写到本地中,实现永久化存储
                   BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("optimizeserver\\ServerDir\\copy.jpg"));
       
                   int b;
                   while((b = bis.read()) !=-1){
                       bos.write(b);
                   }
       
                   BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
                   bw.write("上传成功");
                   bw.newLine();
                   bw.flush();
       
                   bos.close();
                   accept.close();
               }
               //ss.close();
               
           }
       }
       
    
    
    

- 优化方案二

  • 需求
    第二次上传文件的时候,会把第一次的文件给覆盖。
  • 解决方案
    UUID. randomUUID()方法生成随机的文件名
  • 代码实现
    // 服务器代码如下,客户端代码同上个案例,此处不再给出
        public class ServerDemo {
            public static void main(String[] args) throws IOException {
                ServerSocket ss = new ServerSocket(10000);
        
                while (true) {
                    Socket accept = ss.accept();
        
                    //网络中的流,从客户端读取数据的
                    BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
                    //本地的IO流,把数据写到本地中,实现永久化存储
                    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("optimizeserver\\ServerDir\\" + UUID.randomUUID().toString() + ".jpg"));
        
                    int b;
                    while((b = bis.read()) !=-1){
                        bos.write(b);
                    }
        
                    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
                    bw.write("上传成功");
                    bw.newLine();
                    bw.flush();
        
                    bos.close();
                    accept.close();
                }
                //ss.close();
        
            }
        }

- 优化方案三

  • 需求
    使用循环虽然可以让服务器处理多个客户端请求。但是还是无法同时跟多个客户端进行通信。
  • 解决方案
    开启多线程处理
  • 代码实现
    // 线程任务类
        public class ThreadSocket implements Runnable {
            private Socket acceptSocket;
        
            public ThreadSocket(Socket accept) {
                this.acceptSocket = accept;
            }
          
            @Override
            public void run() {
                BufferedOutputStream bos = null;
                try {
                    //网络中的流,从客户端读取数据的
                    BufferedInputStream bis = new BufferedInputStream(acceptSocket.getInputStream());
                    //本地的IO流,把数据写到本地中,实现永久化存储
                    bos = new BufferedOutputStream(new FileOutputStream("optimizeserver\\ServerDir\\" + UUID.randomUUID().toString() + ".jpg"));
        
                    int b;
                    while((b = bis.read()) !=-1){
                        bos.write(b);
                    }
                  
                    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(acceptSocket.getOutputStream()));
                    bw.write("上传成功");
                    bw.newLine();
                    bw.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if(bos != null){
                        try {
                            bos.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
        
                    if (acceptSocket != null){
                        try {
                            acceptSocket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        // 服务器代码
        public class ServerDemo {
            public static void main(String[] args) throws IOException {
                ServerSocket ss = new ServerSocket(10000);
        
                while (true) {
                    Socket accept = ss.accept();
                    ThreadSocket ts = new ThreadSocket(accept);
                    new Thread(ts).start();
                }
                //ss.close();
            }
        }

- 优化方案四

  • 需求
    使用多线程虽然可以让服务器同时处理多个客户端请求。但是资源消耗太大。
  • 解决方案
    加入线程池
  • 代码实现
    // 服务器代码如下,线程任务类代码同上,此处不再给出
        public class ServerDemo {
            public static void main(String[] args) throws IOException {
                ServerSocket ss = new ServerSocket(10000);
                ThreadPoolExecutor pool = new ThreadPoolExecutor(
                        3,//核心线程数量
                        10,   //线程池的总数量
                        60,   //临时线程空闲时间
                        TimeUnit.SECONDS, //临时线程空闲时间的单位
                        new ArrayBlockingQueue<>(5),//阻塞队列
                        Executors.defaultThreadFactory(),//创建线程的方式
                        new ThreadPoolExecutor.AbortPolicy()//任务拒绝策略
                );
        
                while (true) {
                    Socket accept = ss.accept();
                    ThreadSocket ts = new ThreadSocket(accept);
                    //new Thread(ts).start();
                    pool.submit(ts);
                }
                //ss.close();
            }
        }
网络编程入门 计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统网络编程在网络通信协议下,实现网络互连的不同计算机上运行的程序间可以进行数据交换。 阅读详情

相关推荐

java零基础从入门到精通(全)

目录前言1. 入门知识1.1 java体系1.2 JDK/JRE/JVM区别1.3 编译与运行理解1.4 类体函数细节2. 标识符 前言 java优势 健壮性(JVM(C++语言写的一个虚拟的计算机)、GC(垃圾回收机制)) 多线程并发 可移植性/跨平台 1. 入门知识 1.1 java体系 JavaSE:标准版 JavaEE:企业版 JavaME:微型版 1.2 JDK/JRE/JVM区别 JVM是不能独立安装的。 JRE和JDK都是可以独立安装的 层层嵌套,jvm包括jdk,jdk包括jre

码农研究僧的博客 6万+

java编程基础(入门级)(超级完整版)

java基础编程 01基础知识 1.计算机基础 【1】进制 A.十进制转化二进制 除以2,求余数,商继续除以2,一直到0为止,从底下往上得到结果。 B.二进制转化十进制 1 | 1 | 0 | 0 23∣22∣21∣202^3 | 2^2 | 2^1 | 2^023∣22∣21∣20 8+4+0+0=128+4+0+0=128+4+0+0=12 【2】 计算机的储存方式 位(bit):0或1 字节(byte):8位1字节,数据储存的最小单位 1 KB=1024 Byte 1 MB=1024 KB 1 GB=

weixin_41406651的博客 6万+

java网络通信,UDP组播数据收发类及应用示例,可以指定组播收发数据的网卡即组播数据所在网络

通常在主机多网卡的情况下,需要指定组播数据收发的网卡,即向那个网络发送组播数据,从那个网络接收组播数据,否则容易产生接收不到组播数据的情况。代码中给出的组播收发类直接调用即可,收发类可分开使用,通过构造函数的重载,可传参网卡IP,也可在单网卡时不传参。MultiCastRecver为组播数据接收类,MultiCastSender为组播数据发送类,TestMultiCast为收发数据的测试类。

Java 入门 (超级详细)

Java是一种高级编程语言,由Sun Microsystems公司于1995年推出。Java具有跨平台性、面向对象、健壮性、安全性、可移植性等特点,被广泛应用于企业级应用开发、移动应用开发、大数据处理、云计算等领域。Java程序可以在不同的操作系统上运行,只需编译一次,就可以在任何支持Java虚拟机(JVM)的平台上运行。Java还提供了丰富的库和框架,可以加快开发过程,提高开发效率。变量是计算机程序中用于存储数据的一种数据类型。它是一个名称,代表了一个值或一个对象,可以在程序中多次使用。

qq_63519395的博客 10万+

STM32F4系列HAL库配置定时器实验——输入捕获

STM32F4系列HAL库配置定时器实验——输入捕获 输入捕获简单讲解 输入捕获模式可以用来测量脉冲宽度或者测量频率。我们以测量周期和频率为例,用一个简图来说明输入捕获的原理 假定定时器工作在向上计数模式, 图中 t1~t2 时间,就是我们需要测量的高电平时间。测量方法如下:首先设置定时器通道 x 为 上升沿捕获,这样,t1 时刻,就会捕获到当前的 CNT 值,然后立即清零 CNT,并设置通道 x为下降沿捕获,这样到 t2 时刻,又会发生捕获事件,得到此时的 CNT 值,记为 CCRx2。这样,根据定时器

azs0504的博客 9286

ESP-01S使用micropython,利用Thonny烧写固件

在家舒服的太久了,想学习点新的东西,这次看上了ESP8266系列的联网设备,想自己做点小玩意出来耍耍,下面跟我一起来学习吧。本篇主要记录固件的烧写及测试。Thonny下载链接不算难,但是网上资源较少。也是提醒自己不要忘记这个步骤,记录一下,也分享给和我一样开始接触的小伙伴,加油加油,万事开头难。

weixin_43422072的博客 1693

网络编程---网络编程入门、UDP通信程序、TCP通信程序

在网络通信协议下,实现网络互连的不同计算机上运行的程序间可以进行数据传输是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。

weixin_61611746的博客 1169

【Q1/论文复现】:利用 CHARLS 数据库考察抗高血压药物依从性和认知衰退

摘要: 北京大学团队基于CHARLS数据(2011-2018)的纵向研究发现,抗高血压药物高依从性能显著延缓中国45岁及以上社区中老年人的认知衰退。研究表明,坚持服药者7年内全局认知衰退速度降低0.014SD/年,记忆功能衰退减缓0.023SD/年,效果接近正常血压人群水平。研究还提示社会经济地位(SES)可能通过影响用药依从性间接调控认知衰老进程。该成果为高血压管理对认知保护提供了人群级证据,发表于《BMC Medicine》(DOI:10.1186/s12916-025-03949-8)。

dingdianbangni的博客 809

Java核心类库之(网络编程:网络编程入门、UDP通信程序、TCP通信程序)

录 1 网络编程入门 1.1 网络编程概述 1.2 网络编程三要素 1.3 IP地址 1.4 InetAddress的使用 1.5 端口 1.6 协议 2 UDP通信程序 2.1 UDP通信原理 2.2 UDP发送数据 2.3 UDP接收数据

努力让自己发光,对的人才能迎着光而来 1万+

Windows 10/11下Drive Composer Pro 2.9.0完整安装与连接ACS880变频器实战教程

本文详细介绍了在Windows 10/11系统上安装Drive Composer Pro 2.9.0并连接ACS880变频器的完整教程。从系统环境准备、软件安装到许可证配置,再到USB、蓝牙和以太网三种连接方式的实战操作,帮助工业自动化工程师快速掌握ABB变频器的调试技巧。

weixin_32956805的博客 526

【软考中级网络工程师】知识点之常用网络诊断和配置命令

本文聚焦软考中级网络工程师必备的网络诊断和配置命令,详细解析 ipconfig、ping、arp 等 11 类核心命令。涵盖各命令的功能、语法、常用参数及应用场景,如 ipconfig 查看配置、ping 测试连通性等。还通过图呈现命令执行逻辑与流程,助读者理解原理。最后结合软考考点回顾重点并提供真题练习,为备考和实际运维提供全面指导,是掌握网络命令的实用参考。

邓邓子的博客 1546

【java】网络编程入门、UDP通信程序、TCP通信程序

计算机网络:是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统网络编程:在网络通信协议下,实现网络互连的不同计算机上运行的程序间可以进行数据交换。

DreamSun的博客 329

图像处理系列——直方图之直方图规定化(Histogram Specification)

直方图规定化也叫直方图匹配(Histogram Matching),让原图像的像素分布与规定图像的像素分布保持一致。直方图规定化比直方图均衡化更加灵活,算是直方图均衡的变种。常用于图片风格一致性的自动处理,能有效的改善图像的整体或局部的特征,广泛运用在图像增强处理中。

nanke_yh的博客 4594

JavaSE进阶13:网络编程入门、UDP通信程序、TCP通信程序、日志logback、枚举

1.线程池 1.1 线程状态介绍 当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢?Java中的线程 状态被定义在了java.lang.Thread.State枚举类中,State枚举类的源码如下: public class Thread { public enum State { /* 新建 */ NEW , /* 可运行状态

XXXZhy丶Blog 1714

基于YOLO26深度学习框架的人脸识别门禁系统的算法研究实现方法

本文研究了基于YOLO26深度学习框架的人脸识别门禁系统实现方法。系统采用YOLO26目标检测算法,通过CSPDarknet53主干网络、特征金字塔结构和注意力机制实现高效人脸检测。研究内容包括数据预处理、模型训练优化和身份验证等关键技术,使用迁移学习策略和CIoU损失函数提升检测精度。该系统可应用于智能安防场景,具有实时性强、识别准确的特点,为门禁管理提供了智能化解决方案。

一键难忘的博客 766

GEE:使用 CCDC 算法进行连续变化检测和分类

连续变化检测和分类(CCDC)算法是一种广泛应用于遥感数据分析的方法,可以用于检测土地覆盖变化、农作物生长状态的变化以及水资源的变化等。Google Earth Engine是一个强大的云端平台,提供了丰富的遥感数据和工具,可以用于执行各种类型的遥感数据分析。本文将介绍如何使用Google Earth Engine的CCDC算法进行连续变化检测和分类。

养乐多的博客 5679

笔记-15 网络编程入门 UDP通信程序 TCP通信程序 服务端优化

1.网络编程入门 1.1 网络编程概述【理解】 计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统 网络编程 在网络通信协议下,不同计算机上运行的程序,可以进行数据传输 1.2 网络编程三要素【理解】 IP地址 要想让网络中的计算机能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接收数据的计算机和识别发送的计算机,而IP地址就是这个标识号。

qq_45181415的博客 292

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

学习笔记(java)②①(网络编程入门,UDP通信程序,TCP通信程序)

1.网络编程入门 网络编程概述 计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统 网络编程 在网络通信协议下,实现网络互联的不同计算机上运行的程序间可以进行数据交换 网络编程三要素 ①IP地址 要想让网络中的计算机能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接收数据的计算机和识别发送的计算机,而 IP 地址就是这个标识

m0_56655954的博客 162

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Java21-day12【网络编程(网络编程入门(ip地址、端口、协议、InetAddress)、UDP通信程序、TCP通信程序)】

1.1、网络编程概述 1.2、网络编程三要素 1.3、IP地址 1.4、InetAddress的使用 1.5、端口 1.6、协议 2.1、UDP通信原理 2.2、UDP发送数据 2.3、UDP接收数据 2.4、UDP通信程序练习 3.1、TCP通信原理 3.2、TCP发送数据 3.3、TCP接收数据 3.4、TCP通信程序练习

upward 1182

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

笔记-15 网络编程入门 UDP通信程序 TCP通信程序 练习

问答题 题目1 请写出端口号的范围 0 ~ 65535 题目2 判断下列说法是否正确: 由于TCP是面向连接的协议,可以保证数据的完整性,因此在传输重要数据时建议采用TCP协议. 正确,TCP协议是面向连接的,有3次握手的过程,可以保证数据的完整性; 题目3 TCP协议中”三次握手”,指的是什么? 第一次握手,客户端向服务器端发出连接请求,等待服务器确认 第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求 第三次握手,客户端再次向服务器端发送确认信息,确认连接 对应的代码就是 创建客

qq_45181415的博客 581

Java学习笔记(十九):网络编程(入门)、UDP通信程序、TCP通信程序、服务器改写为多线程

计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统网络编程在网络通信协议下,不同计算机上运行的程序,可以进行数据传输。

weixin_62764364的博客 914

c 网络编程程序_网络编程入门 UDP通信程序 TCP通信程序 练习

问答题题目1请写出端口号的范围0 ~ 655351题目2判断下列说法是否正确:由于TCP是面向连接的协议,可以保证数据的完整性,因此在传输重要数据时建议采用TCP协议.正确,TCP协议是面向连接的,有3次握手的过程,可以保证数据的完整性;1题目3TCP协议中”三次握手”,指的是什么?第一次握手,客户端向服务器端发出连接请求,等待服务器确认第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连...

weixin_36379666的博客 107

网络编程入门 网络编程概述【理解】网络编程三要素【理解】 IP地址 端口 协议 IP【理解】 UDP接收数据【应用】 TCP通信程序 TCP接收数据

文章目录网络编程入门*网络编程概述【理解】***网络编程三要素【理解】*IP地址端口协议IP*地址【理解】** 端口和协议【理解】*.UDP通信程序UDP接收数据【应用】TCP通信程序TCP接收数据 网络编程入门 网络编程概述【理解】* 计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系 统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统 网络编程 在网络通信协议下,实现网络互连的不同计算机上运行的程序间可以进行数据交换 网

weixin_54425421的博客 424

十二、Java网络编程

文章目录十二、Java网络编程1.网络编程入门1.1 网络编程概述【理解】1.2 网络编程三要素【理解】1.3 IP地址【理解】1.4InetAddress【应用】1.5端口和协议【理解】2.UDP通信程序2.1 UDP发送数据【应用】2.2UDP接收数据【应用】2.3UDP通信程序练习【应用】3.TCP通信程序3.1TCP发送数据【应用】3.2TCP接收数据【应用】3.3TCP通信程序练习【应用】3.4TCP通信程序练习【应用】3.5TCP通信程序练习【应用】3.6TCP通信程序练习【应用】3.7TCP通

汪随安的博客 2917

【JavaSE】网络编程————IP地址,端口,协议,UDP,TCP

文章目录1.网络编程入门1.1 网络编程概述1.2 网络编程的三要素1.3 IP地址1.4 InetAddress类的使用1.5 端口1.6 协议(UDP/TCP)2. UDP通信程序2.1 UDP通信原理2.2 UDP发送数据2.3 UDP接收数据2.4 UDP通信程序练习3. TCP通信程序3.1 TCP通信原理3.2 TCP发送数据3.3 TCP接收数据3.4 TCP通信程序练习 1.网络编程入门 1.1 网络编程概述 计算机网络: 是指将地理位置不同的句有独立功能的多态计算机及其外部设备,通过通信

weixin_44197120的博客 302
上一篇: JavaSE --- 多线程
下一篇: Java中类加载器与反射
MemoryHer
博客等级 码龄5年 4粉丝 48原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值