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
  • 相关阅读:
    POJ3320 Jessica's Reading Problem
    POJ3320 Jessica's Reading Problem
    CodeForces 813B The Golden Age
    CodeForces 813B The Golden Age
    An impassioned circulation of affection CodeForces
    An impassioned circulation of affection CodeForces
    Codeforces Round #444 (Div. 2) B. Cubes for Masha
    2013=7=21 进制转换
    2013=7=15
    2013=7=14
  • 原文地址:https://www.cnblogs.com/liuzeyu12a/p/10393592.html
Copyright © 2011-2022 走看看