zoukankan      html  css  js  c++  java
  • Java连载127-多线程TCP网络编程

    一、多线程的TCP网络编程

    • 如果需要进行多次数据交互,就可以在程序中设置一个循环,不断向对方发送请求,即可完成多次数据交互。同样,如果需要让服务器同时响应多个客户端的请求,可以使用多线程的方法,也就是服务器端没接收到一个新的连接请求,就启动一个专门的线程与客户端进行交互。
    • 本测试程序可以分为三类:客户端类、服务器类和逻辑线程类
    1. 首先是客户端类
    package com.bjpowernode.java_learning;
    
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.net.Socket;
    import java.util.Scanner;
    
    public class D127_1_ClientTest {
     public static void main(String[] args) {
      Scanner scanner = new Scanner(System.in);
      String input = null;
      Socket socket = null;
      DataInputStream in = null;
      DataOutputStream out = null;
      String serverIP = "127.0.0.1";                           //服务器端IP
      int port = 5050;
      
      try {
       socket = new Socket(serverIP,port);                  //连接服务器
       in = new DataInputStream(socket.getInputStream());   //创建输入流
       out = new DataOutputStream(socket.getOutputStream());//创建输出流
       System.out.println("请输入一个待计算的四则运算表达式");
       
       while(scanner.hasNext()) {
        input = scanner.nextLine();                       //从键盘输入一个待计算的四则运算表达式
        if(!input.contentEquals("0")) {
         out.writeUTF(input);                          //向服务器发送运算请求
         String result = in.readUTF();                 //等待读取运算结果
         System.out.println("服务器返回的计算结果:"+result);
         System.out.println("请输入一个正整数的四则运算表达式(输入0退出):");
         
        }else {
         break;                                        //请求结果
        }
       }
      }catch(Exception e) {
       System.out.println("与服务器连接中断");
      }finally {
       try {
        in.close();                                       //关闭网络连接
        out.close();
        socket.close();
        System.out.println("连接结束");
       }catch(Exception e) {
        
       }
      }
     }
    }
     
    1. 接下来是服务器端类
    package com.bjpowernode.java_learning;
    
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    import com.bjpowernode.java_learning.D127_3_ThreadTest;
    
    public class D127_2_ServerTest {
     public static void main(String[] args) {
      ServerSocket server_socket = null;
      Socket socket = null;
      int port = 5050;
      
      while(true) {
       try {
        server_socket = new ServerSocket(port);
        System.out.println("服务器启动!");
       }catch(IOException e1) {
        System.out.println("正在监听");                   //ServerSocket对象不能重复创建
       }
       
       try {
        System.out.println("等待客户请求!");
        socket = server_socket.accept();
        System.out.println("客户的地址:"+socket.getInetAddress() + ":" + socket.getPort());
       }catch(IOException e) {
        System.out.println("正在等待客户"); 
       }
       
       if(socket!=null) {
        new D127_3_ThreadTest(socket);                          //为每个客户启动一个专门的线程
       }
      }
     }
    }
     
    1. 最后是逻辑线程类
    package com.bjpowernode.java_learning;
    
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.net.Socket;
    
    public class D127_3_ThreadTest extends Thread {
     Socket socket = null;
     DataInputStream in = null;
     DataOutputStream out = null;
     String str;
     String response;
     String ip;
     int port;
     
     public D127_3_ThreadTest(Socket socket) {
      this.socket = socket;
      start();
     }
     
     public void run() {
      try {
       in = new DataInputStream(socket.getInputStream());          //创建输入流
       out = new DataOutputStream(socket.getOutputStream());       //创建输出流
       ip = socket.getInetAddress().getHostAddress();              //客户端IP地址
       port = socket.getPort();                                    //客户端的端口号
       
       while(true) {
        str = in.readUTF();                                     //获取客户端的表达式
        System.out.println("客户端" + ip + ":" + port + "发送的请求内容:");
        System.out.println(str+"=?");
        
        if(str.contentEquals("0")) {
         System.out.println("连接结束");
         break;
        }else {
         response = doComputer(str);                         //对表达式进行计算
         out.writeUTF(response);                             //响应计算结果
        }   
       }  
      }catch(Exception e) {
       System.out.println("连接结束");
      }finally {
       try {
        in.close();
        out.close();
        socket.close();
       }catch(Exception e) {
        
       }
      }
     }
     public String doComputer(String str) {
      String input;
      String[] sym;
      String[] data;
      int a=0,b=0,result=0;
      input = str;
      data = input.split("\D+");
      sym = input.split("\d+");
      a = Integer.parseInt(data[0]);
      b = Integer.parseInt(data[1]);
      
      try {
       switch(sym[1]) {
       case "+":
        result = a + b;
        break;
       case "-":
        result = a - b;
        break;
       case "*":
        result = a * b;
        break;
       case "/":
        result = a / b;
       }
       System.out.println("计算结果:"+input+"="+result);
       return String.valueOf(result);
      }catch(java.lang.ArithmeticException e) {
       System.out.println("数据错误!");
       return "数据错误";
      }
     }
    
    }
     
    1. 这样我们就做完了所有的工作,那么接下来进行启动该项目
    • 首先启动服务器的类,运行结果如下:
      127.1
    • 然后启动客户端类
      127.2
    • 我们在客户端类中cosole界面输入3*5然后回车
      127.3
    • 从上面的运行结果来看,得到了我们想要的结果,那么接下来输入0来结束这个项目的运行
      127.4

    总结:在编写代码过程中我们遇到的问题,或者以前忘记的知识点:
    1.服务器端类中:
    (1)server_socket.accept() 一直处于阻塞直到接收了socket发来的请求,并返回一个socket对象;
    (2)写一了一个多线程类,来给每个客户一个线程;
    2.客户端类 (1)DataInputStream(socket.getInputStream()) socket的成员方法来获取输入流,并返回一个InputStream对象,然后经过java.io.DataInputStream方法转换为专有的流。
    (2)DataOutputStream对象.writeUTF(String result) 用于传入字符串
    (3)DataInputStream对象.readUTF() 用于读取字符串
    3.多线程类
    (1) 多线程重写了run方法
    (2) 客户端和服务器端的读和写是正相反的。

    二、源码:

      • D127_1_ClientTest.java
      • D127_2_ServerTest.java
      • D127_3_ThreadTest.java
      • https://github.com/ruigege66/Java/blob/master/D127_1_ClientTest.java
      • https://github.com/ruigege66/Java/blob/master/D127_2_ServerTest.java
      • https://github.com/ruigege66/Java/blob/master/D127_3_ThreadTest.java
      • CSDN:https://blog.csdn.net/weixin_44630050
      • 博客园:https://www.cnblogs.com/ruigege0000/
      • 欢迎关注微信公众号:傅里叶变换,个人账号,仅用于技术交流,后台回复“礼包”获取Java大数据学习视频礼包
      • 127.59
  • 相关阅读:
    Eureka与ZooKeeper 的比较(转)
    springcloud 与分布式系统(转载)
    jvm 分代回收算法通俗理解
    关于JVM调优
    Java常用的数据结构
    mysql数据库引擎(转载)
    java的堆栈通俗理解
    ArrayList 的实现原理
    hashMap 源码解读理解实现原理和hash冲突
    Sklearn库例子——决策树分类
  • 原文地址:https://www.cnblogs.com/ruigege0000/p/13245779.html
Copyright © 2011-2022 走看看