TCP通信原理

TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象,从而在通信的两端形成虚拟网络链路。一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信
image.png

TCP发送数据

发送数据步骤

  1. 创建客户端的Socket对象(Socket) Socket(String host,int port)
  2. 获取输出流,写数据
    OutputStream getOutputStream()
  3. 释放资源 void close()

    //创建客户端的Socket对象(Socket)
    //Socket(InetAddress address,int port)创建流套接字并将将其连接到指定IP地址的指定端口号
    Socket s = new Socket(InetAddress.getByName("192.168.1.66"),,port:10000);//alt enter 抛出异常
    //Socket(String host,int port)创建流套接字并将将其连接到指定IP地址的指定端口号 
    //和前面那个一样 只是第一个参数可以直接是字符串地址
    Socket s = new Socket(host:"192.168.1.66",port:10000);//alt enter 抛出异常
    
    //获取输出流,写数据
    //OutputStream getOutputStream() 返回此套接字的输出流
    OutputStream os = s.getOutputStream();
    os.write(b:"hello,tcp,我来了".getBytes())
    //释放资源
    s.close();

TCP接收数据

接收数据步骤

  1. 创建服务器端的Socket对象(ServerSocket)
    ServerSocket(int port)
  2. 监听客户端连接,返回一个Socket对象 Socket accept()
  3. 获取输入流,读数据,并把数据显示在控制台 InputStream getInputStream()
  4. 释放资源 void close()

    //创建服务器端的Socket对象(ServerSocket)
    //ServerSocket(int port)创建绑定到指定端口的服务器套接字
    ServerSocket ss = new ServerSocket(port:10000);//alt enter 抛出异常
    
    //Socket accept() 侦听要连接到此套接字并接受它
    Socket s = ss.accept();
    //获取输入流,读数据,并把数据显示在控制台
    //InputStream getInputStream() 返回此套接字的输出流
    InputStream is = s.getInputStream();
    byte[] bys = new byte[1024];
    int len = is.read(bys);//拿到的是实际发送了多少数据
    String dataString = new String(bys,offset:0,len);
    sout("数据是:"+dataString);
    //释放资源
    s.close();
    ss.close();

TCP通信程序练习

练习1

  • 客户端:发送数据,接收服务器反馈
  • 服务器:接收数据,给出反馈
    客户端程序

    //创建客户端的Socket对象(Socket)
    Socket s = new Socket(host:"192.168.1.66",port:10000);//alt enter 抛出异常
    
    //获取输出流,写数据
    OutputStream os = s.getOutputStream();
    os.write(b:"hello,tcp,我来了".getBytes())
    
    //接收服务器反馈
    InputStream is = s.getInputStream();
    byte[] bys = new byte[1024];
    int len = is.read(bys);//拿到的是实际发送了多少数据
    String data = new String(bys,offset:0,len);
    sout("客户端:"+data);
    //释放资源
    s.close();

    服务器端程序

    //创建服务器端的Socket对象(ServerSocket)
    ServerSocket ss = new ServerSocket(port:10000);//alt enter 抛出异常
    
    //监听客户端连接,返回一个Socket对象
    Socket s = ss.accept();
    
    //获取输入流,读数据,并把数据显示在控制台
    InputStream is = s.getInputStream();
    byte[] bys = new byte[1024];
    int len = is.read(bys);//拿到的是实际发送了多少数据
    String data = new String(bys,offset:0,len);
    sout("服务器:"+data );
    
    //给出反馈
    OutputStream os = s.getOutputStream();
    os.write("数据已经收到".getBytes());
    
    //释放资源
    s.close();
    ss.close();

    练习2

  • 客户端:数据来自于键盘录入,直到输入的数据是886,发送数据结束
  • 服务器:接收到的数据在控制台输出
    客户端程序

    //创建客户端的Socket对象(Socket)
    Socket s = new Socket(host:"192.168.1.66",port:10000);//alt enter 抛出异常
    
    //数据来自于键盘录入,直到输入的数据是886,发送数据结束
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    //封装输出流对象
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));//字节输出流转化成字符流,然后用BufferedWriter写数据封装
    String line;
    while((line=br.readLine())!=null){//alt enter 抛出异常
        //所输入的数据是886,发送数据结束
        if("886".equals(line)){
            break;
        }
        //如果不是,就获取输出流对象
        //OutputStream os = s.getOutputStream();
        //os.write(b:"hello,tcp,我来了".getBytes());
        bw.write(line);
        bw.newLine();
        bw.flush();
    }
    
    //释放资源
    s.close();

    服务器端程序

    //创建服务器端的Socket对象(ServerSocket)
    ServerSocket ss = new ServerSocket(port:10000);//alt enter 抛出异常
    
    //监听客户端连接,返回一个对应的Socket对象
    Socket s = ss.accept();
    
    //获取输入流,读数据,并把数据显示在控制台
    InputStream is = s.getInputStream();
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    //上面三步合并为
    BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));//输入流转化成字符流,再包装成BufferedReader
    String line;
    while((line=br.readLine())!=null){//alt enter 抛出异常
        sout(line);
    }
    
    //释放资源
    ss.close();

    练习3

  • 客户端:数据来自于键盘录入,直到输入的数据是886,发送数据结束
  • 服务器:接收到的数据写入文本文件
    客户端程序

    //创建客户端的Socket对象(Socket)
    Socket s = new Socket(host:"192.168.1.66",port:10000);//alt enter 抛出异常
    
    //数据来自于键盘录入,直到输入的数据是886,发送数据结束
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    //封装输出流对象
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));//字节输出流转化成字符流,然后用BufferedWriter写数据封装
    String line;
    while((line=br.readLine())!=null){//alt enter 抛出异常
        //所输入的数据是886,发送数据结束
        if("886".equals(line)){
            break;
        }
        //如果不是,就获取输出流对象
        //OutputStream os = s.getOutputStream();
        //os.write(b:"hello,tcp,我来了".getBytes());
        bw.write(line);
        bw.newLine();
        bw.flush();
    }
    
    //释放资源
    s.close();

    服务器端程序

    //创建服务器端的Socket对象(ServerSocket)
    ServerSocket ss = new ServerSocket(port:10000);//alt enter 抛出异常
    
    //监听客户端连接,返回一个对应的Socket对象
    Socket s = ss.accept();
    
    //接收数据
    BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));//输入流转化成字符流,再包装成BufferedReader
    //把数据写入文本文件
    BufferedWriter bw = new BufferedWriter(new FileWriter(fileName:"myNet\\s.txt"));
    
    String line;
    while((line=br.readLine())!=null){//alt enter 抛出异常
        bw.write(line);
        bw.newLine();
        bw.flush();
    }
    
    //释放资源
    bw.close();
    ss.close();

    练习4

  • 客户端:数据来自于文本文件
  • 服务器:接收到的数据写入文本文件
    客户端程序

    //创建客户端的Socket对象(Socket)
    Socket s = new Socket(host:"192.168.1.66",port:10000);//alt enter 抛出异常
    
    //数据来自于文本文件
    //封装文本文件的数据
    BufferedReader br = new BufferedReader(new FileReader(fileName:"myNet\\InetAddressDemo.java"));
    //封装输出流写数据
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));//字节输出流转化成字符流,然后用BufferedWriter写数据封装
    
    //读数据,并且把它写出去
    String line;
    while((line=br.readLine())!=null){//alt enter 抛出异常
        bw.write(line);
        bw.newLine();
        bw.flush();
    }
    
    //释放资源
    br.close();
    s.close();

    服务器端程序

    //创建服务器端的Socket对象(ServerSocket)
    ServerSocket ss = new ServerSocket(port:10000);//alt enter 抛出异常
    
    //监听客户端连接,返回一个对应的Socket对象
    Socket s = ss.accept();
    
    //接收数据
    BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));//输入流转化成字符流,再包装成BufferedReader
    //把数据写入文本文件
    BufferedWriter bw = new BufferedWriter(new FileWriter(fileName:"myNet\\Copy.java"));
    
    String line;
    while((line=br.readLine())!=null){//alt enter 抛出异常
        bw.write(line);
        bw.newLine();
        bw.flush();
    }
    
    //释放资源
    bw.close();
    ss.close();

    练习5

  • 客户端:数据来自于文本文件,接收服务器反馈
  • 服务器:接收到的数据写入文本文件,给出反馈

    • 出现问题:程序一直等待
    • 原因:读数据的方法是阻塞式的

    客户端程序

    //创建客户端的Socket对象(Socket)
    Socket s = new Socket(host:"192.168.1.66",port:10000);//alt enter 抛出异常
    
    //数据来自于文本文件
    //封装文本文件的数据
    BufferedReader br = new BufferedReader(new FileReader(fileName:"myNet\\InetAddressDemo.java"));
    //封装输出流写数据
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));//字节输出流转化成字符流,然后用BufferedWriter写数据封装
    
    //读数据,并且把它写出去
    String line;
    while((line=br.readLine())!=null){//alt enter 抛出异常
        bw.write(line);
        bw.newLine();
        bw.flush();
    }
    
    //自定义结束标记
    //bw.write(str:"886");
    //bw.newLine();
    //bw.flush();
    
    //public void shutdownOutput()
    s.shutdownOutput();
    //接收服务器的反馈
    BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
    String data = brClient.readLine();//等待读取数据
    sout("服务器的反馈:"+data);
    
    //释放资源
    br.close();
    s.close();

    服务器端程序

    //创建服务器端的Socket对象(ServerSocket)
    ServerSocket ss = new ServerSocket(port:10000);//alt enter 抛出异常
    
    //监听客户端连接,返回一个对应的Socket对象
    Socket s = ss.accept();
    
    //接收数据
    BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));//输入流转化成字符流,再包装成BufferedReader
    //把数据写入文本文件
    BufferedWriter bw = new BufferedWriter(new FileWriter(fileName:"myNet\\Copy.java"));
    
    String line;
    while((line=br.readLine())!=null){//alt enter 抛出异常  还在这等着读数据呢
     //   if("886".equals(line)){
    //        break;
    //    }
        bw.write(line);
        bw.newLine();
        bw.flush();
    }
    
    //给出反馈
    BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); 
    bwServer.write(str:"文件上传成功");
    bwServer.newLine();
    bwServer.flush();
    
    //释放资源
    bw.close();
    ss.close();

    练习6

  • 客户端:数据来自于文本文件,接收服务器反馈
  • 服务器:接收到的数据写入文本文件,给出反馈,代码用线程进行封装,为每一个客户端开启一个线程
    客户端程序

    //创建客户端的Socket对象(Socket)
    Socket s = new Socket(host:"192.168.1.66",port:10000);//alt enter 抛出异常
    
    //数据来自于文本文件
    //封装文本文件的数据
    BufferedReader br = new BufferedReader(new FileReader(fileName:"myNet\\InetAddressDemo.java"));
    //封装输出流写数据
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));//字节输出流转化成字符流,然后用BufferedWriter写数据封装
    
    //读数据,并且把它写出去
    String line;
    while((line=br.readLine())!=null){//alt enter 抛出异常
        bw.write(line);
        bw.newLine();
        bw.flush();
    }
    
    //自定义结束标记
    //bw.write(str:"886");
    //bw.newLine();
    //bw.flush();
    
    //public void shutdownOutput()
    s.shutdownOutput();
    //接收服务器的反馈
    BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
    String data = brClient.readLine();//等待读取数据
    sout("服务器的反馈:"+data);
    
    //释放资源
    br.close();
    s.close();

    服务器端程序

    //创建服务器端的Socket对象(ServerSocket)
    ServerSocket ss = new ServerSocket(port:10000);//alt enter 抛出异常
    
    while(true){
        //监听客户端连接,返回一个对应的Socket对象
        Socket s = ss.accept();
    
        //为每一个客户端开启一个线程
        new Thread(new ServerThread(s)).start();
    }

    创建一个类实现线程

    public class ServerThread implements Runnable{
       private Socket s;
       
       public ServerThread (Socket s){
           this.s = s;
       }
       //重写run方法
       @Override
       public void run(){
          //接收数据,写到文本文件
          BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));//try catch捕获异常
          //BufferedWriter bw = new BufferedWriter(new FileWriter(fileName:"myNet\\Copy.java"));
          //解决名称冲突问题
          int count = 0;
          File file = new File(pathname:"myNet\\Copy["+count+"].java");
          while(file.exists()){
              count++;
              file = new File(pathname:"myNet\\Copy["+count+"].java");
          }
          BufferedWriter bw = new BufferedWriter(new FileWriter(file));
          
          String line;
          while((line=br.readLine())!=null){
              bw.write(line);
              bw.newLine();
              bw.flush();
          }
          //给出反馈
          BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); 
          bwServer.write(str:"文件上传成功");
          bwServer.newLine();
          bwServer.flush();
          //释放资源
          s.close();
       }
    }

    image.png


Loccy
4 声望1 粉丝

« 上一篇
UDP通信程序
下一篇 »
Lambda表达式