zoukankan      html  css  js  c++  java
  • 网络编程之TCP通信

    1、TCP协议是面向连接的、可靠的、有序的、以字节流的方式发送数据,通过三次握手方式建立连接,形成传输数据的通道,在连接中进行大量数据的传输,效率会稍低

    2、Java中基于TCP协议实现网络通信的类

                客户端的Socket类
                服务器端的ServerSocket类

     3、Socket通信的步骤

           ① 创建ServerSocket和Socket(服务端和客户端)
           ② 打开连接到Socket的输入/输出流
           ③ 按照协议对Socket进行读/写操作
           ④ 关闭输入输出流、关闭Socket
     
    4、服务器端:
            ① 创建ServerSocket对象,绑定监听端口
            ② 通过accept()方法监听客户端请求
            ③ 连接建立后,通过输入流读取客户端发送的请求信息
            ④ 通过输出流向客户端发送回音信息
            ⑤ 关闭相关资源(大型服务器一般不关闭)
     1 package tcp通信;
     2 
     3 import java.io.DataInputStream;
     4 import java.io.DataOutputStream;
     5 import java.io.IOException;
     6 import java.net.ServerSocket;
     7 import java.net.Socket;
     8 
     9 /**
    10  * 熟悉流程:
    11  * 创建服务器
    12  * 模拟登录界面,单向访问
    13  * 1、指定端口,使用ServerSocket 创建服务器
    14  * 2、阻塞式等待连接accept
    15  * 3、输入输出流操作
    16  * 4、释放资源
    17  * @author liuzeyu12a
    18  *
    19  */
    20 public class LoginServer2 {
    21 
    22     public static void main(String[] args) throws IOException {
    23         System.out.println("---------服务端-----------");
    24         String uname = "";
    25         String upwd = "";
    26         // 1、指定端口 使用ServerSocket创建服务器
    27         ServerSocket server = new ServerSocket(8888);
    28         
    29         //2、阻塞时等待连接,返回一个连接的套接字
    30         Socket client = server.accept();
    31         System.out.println("一个客户端建立了连接...");
    32         
    33         //3、输入输出操作,使用操作方便的数据流
    34         DataInputStream dis = new DataInputStream(client.getInputStream());
    35         String utf = dis.readUTF();
    36         String str[] = utf.split("&");
    37         for(String info:str) {
    38             String[] usrInfo = info.split("=");
    39             if(usrInfo[0].equals("uname")) {
    40                 uname = usrInfo[1];
    41                 System.out.println(usrInfo[0]+":"+usrInfo[1]);
    42             }else{
    43                 upwd = usrInfo[1];
    44                 System.out.println(usrInfo[0]+":"+usrInfo[1]);
    45             }
    46         }
    47         //向客户端返回结果,是否登录成功
    48         DataOutputStream dos = new DataOutputStream(client.getOutputStream());
    49         if(uname.equals("liuzeyu12a")&&upwd.equals("10086")) {
    50             dos.writeUTF("登录成功!!");
    51         }else {
    52             dos.writeUTF("登录失败!!");
    53         }
    54         //释放资源
    55         server.close();  //大型服务器一般不关闭
    56         
    57     }
    58 }
    View Code
     
    5、客户端:       
       ① 创建Socket对象,指明需要连接的服务器的地址和端口号
       ② 连接建立后,通过输出流想服务器端发送请求信息
            ③ 通过输入流获取服务器响应的信息
            ④ 关闭响应资源 
     1 package tcp通信;
     2 
     3 import java.io.BufferedReader;
     4 import java.io.DataInputStream;
     5 import java.io.DataOutputStream;
     6 import java.io.IOException;
     7 import java.io.InputStreamReader;
     8 import java.net.Socket;
     9 import java.net.UnknownHostException;
    10 
    11 /**
    12  * 熟悉流程:
    13  * 模拟登录界面,单向访问
    14  * 1、建立连接,使用Socket创建客户端 + 服务器地址和端口
    15  * 2、输入输出操作
    16  * 3、释放资源
    17  * @author liuzeyu12a
    18  *
    19  */
    20 public class LoginClient2 {
    21 
    22     public static void main(String[] args) throws UnknownHostException, IOException {
    23         System.out.println("---------客户端登录界面-----------");
    24         BufferedReader reader = new BufferedReader(
    25                 new InputStreamReader(System.in));
    26         System.out.print("请输入用户名:");
    27         String uname = reader.readLine();
    28         System.out.print("请输入用户名:");
    29         String upwd = reader.readLine();
    30         
    31         
    32         //1、建立连接,使用Socket创建客户端 + 服务器地址和端口
    33         Socket client = new Socket("localhost",8888);
    34         
    35         //2、输入输出操作
    36         DataOutputStream dos = new DataOutputStream(client.getOutputStream());
    37         dos.writeUTF("uname="+uname+"&"+"upwd="+upwd);
    38         
    39     
    40         //接收服务器返回的结果
    41         DataInputStream dis = new DataInputStream(client.getInputStream());
    42         String rst = dis.readUTF();
    43         System.out.println(rst);
    44         //3、释放资源
    45         dos.close();
    46         client.close();
    47     }
    48 }
    View Code

    6、当然,这种客户端请求服务器,然后服务器回应客户端的请求只能实现一对一的服务,在现在的信息化时代,这种通信已经不能满足需求了。

    一个服务器应该被多个客户端请求,然后对其一一回应,这才是我们想要的。

    这就引出了多线程,在服务器上开启多线程,即一个Socket 多个客户端可以使用。

    应用多线程实现服务器与多客户端之间的通信

           ① 服务器端创建ServerSocket,循环调用accept()等待客户端连接
           ② 客户端创建一个socket并请求和服务器端连接
           ③ 服务器端接受客户端请求,创建socket与该客户建立专线连接
           ④ 建立连接的两个socket在一个单独的线程上对话
           ⑤ 服务器端继续等待新的连接

    实现代码:

    6.1服务端

      1 package tcp通信;
      2 
      3 import java.io.DataInputStream;
      4 import java.io.DataOutputStream;
      5 import java.io.IOException;
      6 import java.net.ServerSocket;
      7 import java.net.Socket;
      8 
      9 /**
     10  * 服务端接收多个客户端的请求:
     11  * 在没有使用多线程的情况下要想多个客户机访问服务器,必须等待上一个服务结束
     12  * 后才能进行下一个客户机的连接操作
     13  * 1、使用ServerSocket 建立服务端的套接字绑定本地端口
     14  * 2、阻塞式等待连接Socket accept()
     15  * 3、输入输出流操作
     16  * 4、释放资源
     17  * @author liuzeyu12a
     18  *
     19  */
     20 public class MultiServer {
     21 
     22     public static void main(String[] args) throws Exception {
     23         System.out.println("-------服务器--------");
     24 
     25         boolean isRunning = true;
     26         //1、使用ServerSocket 建立服务端的套接字绑定本地端口
     27         ServerSocket server = new ServerSocket(9999);
     28         
     29         while(isRunning) {
     30             //2、阻塞式等待连接Socket accept()
     31             Socket client = server.accept();
     32             System.out.println("一个客户端建立了连接");
     33             new Thread(new Channel(client)).start();
     34         }
     35         //4、释放资源
     36         server.close();
     37     }
     38     
     39     
     40     //多线程类
     41     //将类改为静态:否则创建对象:new MultiServer().new Channel(client)
     42     //一个Channel代表了一个客户端
     43      static class Channel implements Runnable{
     44          //客户端套接字
     45         private Socket client;
     46         //输入流
     47         private DataInputStream dis;
     48         //输出流
     49         private DataOutputStream dos;
     50         //构造器
     51         public Channel(Socket client) {
     52             this.client = client;
     53             try {
     54                 dis = new DataInputStream(client.getInputStream());
     55                 dos = new DataOutputStream(client.getOutputStream());
     56             } catch (IOException e) {
     57                 e.printStackTrace();
     58                 //如果出异常了
     59                 try {
     60                     client.close();
     61                 } catch (IOException e1) {
     62                     e1.printStackTrace();
     63                     release();
     64                 }
     65             }
     66         }
     67         
     68         //接收客户端信息函数
     69         public String recvive() {
     70             String datas = "";
     71             try {
     72                 datas = dis.readUTF();
     73             } catch (IOException e) {
     74                 e.printStackTrace();
     75             }
     76             return datas;
     77         }
     78         
     79         //发送客户端信息函数
     80         public void send(String msg) {
     81             try {
     82                 dos.writeUTF(msg);
     83                 dos.flush();
     84             } catch (IOException e) {
     85                 e.printStackTrace();
     86             }
     87         }
     88         
     89         public void release() {
     90             try {
     91                 if(null!=client)
     92                 client.close();
     93             } catch (IOException e) {
     94                 e.printStackTrace();
     95             }
     96             try {
     97                 if(null!=dis)
     98                 dis.close();
     99             } catch (IOException e) {
    100                 e.printStackTrace();
    101             }
    102             try {
    103                 if(null!=dos)
    104                 dos.close();
    105             } catch (IOException e) {
    106                 e.printStackTrace();
    107             }
    108         }
    109         
    110         //线程运行函数
    111         @Override
    112         public void run() {        
    113             //处理客户端发送过来的用户信息
    114             String uname = "";
    115             String upwd = "";
    116             String info[] = recvive().split("&");
    117             for(String str: info) {
    118                 String[] s = str.split("=");
    119                 if(s[0].equals("uname")) {
    120                     uname = s[1];
    121                 }else if(s[0].equals("upwd")) {
    122                     upwd = s[1];
    123                 }            
    124             }
    125             System.out.println("user:"+uname+"
    "+"password:"+upwd);
    126             
    127             //向客户端返回登录信息
    128             if(uname.equals("liuzeyu") &&upwd.equals("10086")) {
    129                 send("登录成功!!");
    130             }else {
    131                 send("登录失败!!");
    132             }    
    133             release();
    134         }    
    135     }
    136 
    137 }
    View Code

    6.2客户端

     1 package tcp通信;
     2 
     3 import java.io.BufferedReader;
     4 import java.io.DataInputStream;
     5 import java.io.DataOutputStream;
     6 import java.io.IOException;
     7 import java.io.InputStreamReader;
     8 import java.net.Socket;
     9 import java.net.UnknownHostException;
    10 
    11 /**
    12  * 熟悉流程:
    13  * 模拟登录界面,单向访问
    14  * 1、建立连接,使用Socket创建客户端 + 服务器地址和端口
    15  * 2、输入输出操作
    16  * 3、释放资源
    17  * @author liuzeyu12a
    18  *
    19  */
    20 public class LoginClient2 {
    21 
    22     public static void main(String[] args) throws UnknownHostException, IOException {
    23         System.out.println("---------客户端登录界面-----------");
    24         BufferedReader reader = new BufferedReader(
    25                 new InputStreamReader(System.in));
    26         System.out.print("请输入用户名:");
    27         String uname = reader.readLine();
    28         System.out.print("请输入用户名:");
    29         String upwd = reader.readLine();
    30         
    31         
    32         //1、建立连接,使用Socket创建客户端 + 服务器地址和端口
    33         Socket client = new Socket("localhost",8888);
    34         
    35         //2、输入输出操作
    36         DataOutputStream dos = new DataOutputStream(client.getOutputStream());
    37         dos.writeUTF("uname="+uname+"&"+"upwd="+upwd);
    38         
    39     
    40         //接收服务器返回的结果
    41         DataInputStream dis = new DataInputStream(client.getInputStream());
    42         String rst = dis.readUTF();
    43         System.out.println(rst);
    44         //3、释放资源
    45         dos.close();
    46         client.close();
    47     }
    48 }
    View Code

    7、客户端利用面向对象思想进行封装后

    7.1 服务端

      1 package tcp通信;
      2 
      3 import java.io.DataInputStream;
      4 import java.io.DataOutputStream;
      5 import java.io.IOException;
      6 import java.net.ServerSocket;
      7 import java.net.Socket;
      8 
      9 /**
     10  * 服务端接收多个客户端的请求:
     11  * 在没有使用多线程的情况下要想多个客户机访问服务器,必须等待上一个服务结束
     12  * 后才能进行下一个客户机的连接操作
     13  * 1、使用ServerSocket 建立服务端的套接字绑定本地端口
     14  * 2、阻塞式等待连接Socket accept()
     15  * 3、输入输出流操作
     16  * 4、释放资源
     17  * @author liuzeyu12a
     18  *
     19  */
     20 public class MultiServer {
     21 
     22     public static void main(String[] args) throws Exception {
     23         System.out.println("-------服务器--------");
     24 
     25         boolean isRunning = true;
     26         //1、使用ServerSocket 建立服务端的套接字绑定本地端口
     27         ServerSocket server = new ServerSocket(9999);
     28         
     29         while(isRunning) {
     30             //2、阻塞式等待连接Socket accept()
     31             Socket client = server.accept();
     32             System.out.println("一个客户端建立了连接");
     33             new Thread(new Channel(client)).start();
     34         }
     35         //4、释放资源
     36         server.close();
     37     }
     38     
     39     
     40     //多线程类
     41     //将类改为静态:否则创建对象:new MultiServer().new Channel(client)
     42     //一个Channel代表了一个客户端
     43      static class Channel implements Runnable{
     44          //客户端套接字
     45         private Socket client;
     46         //输入流
     47         private DataInputStream dis;
     48         //输出流
     49         private DataOutputStream dos;
     50         //构造器
     51         public Channel(Socket client) {
     52             this.client = client;
     53             try {
     54                 dis = new DataInputStream(client.getInputStream());
     55                 dos = new DataOutputStream(client.getOutputStream());
     56             } catch (IOException e) {
     57                 e.printStackTrace();
     58                 //如果出异常了
     59                 try {
     60                     client.close();
     61                 } catch (IOException e1) {
     62                     e1.printStackTrace();
     63                 }
     64             }
     65         }
     66         
     67         //接收客户端信息函数
     68         public String recvive() {
     69             String datas = "";
     70             try {
     71                 datas = dis.readUTF();
     72             } catch (IOException e) {
     73                 e.printStackTrace();
     74             }
     75             return datas;
     76         }
     77         
     78         //发送客户端信息函数
     79         public void send(String msg) {
     80             try {
     81                 dos.writeUTF(msg);
     82                 dos.flush();
     83             } catch (IOException e) {
     84                 e.printStackTrace();
     85             }
     86         }
     87         
     88         public void release() {
     89             try {
     90                 if(null!=client)
     91                 client.close();
     92             } catch (IOException e) {
     93                 e.printStackTrace();
     94             }
     95             try {
     96                 if(null!=dis)
     97                 dis.close();
     98             } catch (IOException e) {
     99                 e.printStackTrace();
    100             }
    101             try {
    102                 if(null!=dos)
    103                 dos.close();
    104             } catch (IOException e) {
    105                 e.printStackTrace();
    106             }
    107         }
    108         
    109         //线程运行函数
    110         @Override
    111         public void run() {        
    112             //处理客户端发送过来的用户信息
    113             String uname = "";
    114             String upwd = "";
    115             String info[] = recvive().split("&");
    116             for(String str: info) {
    117                 String[] s = str.split("=");
    118                 if(s[0].equals("uname")) {
    119                     uname = s[1];
    120                 }else if(s[0].equals("upwd")) {
    121                     upwd = s[1];
    122                 }            
    123             }
    124             System.out.println("user:"+uname+"
    "+"password:"+upwd);
    125             
    126             //向客户端返回登录信息
    127             if(uname.equals("liuzeyu") &&upwd.equals("10086")) {
    128                 send("登录成功!!");
    129             }else {
    130                 send("登录失败!!");
    131             }    
    132             release();
    133         }    
    134     }
    135 
    136 }
    View Code

    7.2  客户端

      1 package tcp通信;
      2 
      3 import java.io.BufferedInputStream;
      4 import java.io.BufferedReader;
      5 import java.io.DataInputStream;
      6 import java.io.DataOutputStream;
      7 import java.io.IOException;
      8 import java.io.InputStreamReader;
      9 import java.net.Socket;
     10 import java.net.UnknownHostException;
     11 
     12 /**模拟多个客户端的请求
     13  * 在没有使用多线程的情况下要想多个客户机访问服务器,必须等待上一个服务结束
     14  * 后才能进行下一个客户机的连接操作
     15  * 客户端
     16  * 1、建立连接,使用多Socket建立客户端+绑定服务器的端口和地址
     17  * 2、操作,输入流和输出流的操作
     18  * 3、释放资源
     19  * @author liuzeyu12a
     20  *
     21  */
     22 public class MultiClient {
     23 
     24     public static void main(String[] args) throws UnknownHostException, IOException {
     25         System.out.println("--------客户端---------");
     26         
     27         //1、建立连接,使用多Socket建立客户端+绑定服务器的端口和地址
     28         Socket client = new Socket("localhost",9999);
     29         
     30         //2、操作,输入流和输出流的操作
     31         new Send(client).send();;
     32         
     33         //处理登录信息的反馈
     34         new Receive(client).receive();
     35         
     36         //释放资源
     37         new Send().release();
     38         new Receive().release();
     39     }
     40     
     41     //静态内部类:用于发送
     42     static class Send{
     43         private String msg = "";
     44         private BufferedReader reader; 
     45         
     46         //输出流
     47         private DataOutputStream dos;
     48         //客户端套接字
     49         private Socket client;
     50         //构造器
     51         public Send(Socket client) {
     52             this.client =client;
     53             this.reader= new BufferedReader(
     54                     new InputStreamReader(System.in));
     55             this.msg = init();
     56             try {
     57                 dos = new DataOutputStream(client.getOutputStream());
     58             } catch (IOException e) {
     59                 e.printStackTrace();
     60             }
     61         }
     62         //无参构造器
     63         public Send() {
     64         }
     65         
     66         //发送函数
     67         public void send() {
     68             try {
     69                 dos.writeUTF(msg);
     70             } catch (IOException e) {
     71                 e.printStackTrace();
     72             }
     73             try {
     74                 dos.flush();
     75             } catch (IOException e) {
     76                 e.printStackTrace();
     77             }
     78         }
     79         //释放资源函数
     80         public void release() {
     81             try {
     82                 if(null!=dos)
     83                 dos.close();
     84             } catch (IOException e1) {
     85                 e1.printStackTrace();
     86             }
     87             try {
     88                 if(null!=client)
     89                 client.close();
     90             } catch (IOException e) {
     91                 e.printStackTrace();
     92             }
     93         }
     94         
     95         //初始化信息
     96         public String init() {    
     97             try {
     98                 System.out.print("请输入用户名:");
     99                 String uname = reader.readLine();
    100                 System.out.print("请输入密码:");
    101                 String upwd = reader.readLine();
    102                 return "uname="+uname+"&"+"upwd="+upwd;
    103             } catch (IOException e) {
    104                 e.printStackTrace();
    105             }
    106             return "";
    107         }
    108         
    109     }
    110 
    111 
    112     //静态内部类:用于接收
    113     static class Receive{
    114         //客户端套接字
    115         private Socket client;
    116         //输入流
    117         private DataInputStream dis;
    118         //构造器
    119         public Receive(Socket client) {
    120             this.client =client;
    121             try {
    122                 dis = new DataInputStream(
    123                         new BufferedInputStream(client.getInputStream()));
    124             } catch (IOException e) {
    125                 e.printStackTrace();
    126             }    
    127             }
    128         
    129         //接收函数
    130         public void receive() {
    131             try {
    132                 String rst = dis.readUTF();
    133                 System.out.println(rst);
    134             } catch (IOException e) {
    135                 e.printStackTrace();
    136             }
    137         }
    138         
    139         public Receive() {
    140         }
    141         //释放函数
    142         public void release() {
    143             try {
    144                 if(null!=client)
    145                 client.close();
    146             } catch (IOException e) {
    147                 e.printStackTrace();
    148             }
    149             try {
    150                 if(null!=dis)
    151                 dis.close();
    152             } catch (IOException e) {
    153                 e.printStackTrace();
    154             }
    155         }
    156     
    157     }
    158 }
    View Code
     

    附上参考资料

    https://www.cnblogs.com/rocomp/p/4790340.html
  • 相关阅读:
    HDU
    HDU
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/liuzeyu12a/p/10393592.html
Copyright © 2011-2022 走看看