网络基础编程:TCP协议

简介: 网络基础编程:TCP协议

一:TCP协议基础知识

a:TCP协议提供API的两个核心类

ServerSocket 产生服务器的端口号
Socket 既能产生服务器的端口号,也能产生客户端的端口号

b:对于TCP协议的连接解析

在前面学习的过程中,我们学习到传输层的TCP协议是有连接的,即服务器和客户端进行连接.接下来,我将进行进一步的解释说明:

1):服务器有一个,而客户端有多个.且服务器和客户端之间连接代表服务器保存客户端的信息,客户端保存服务器的信息

  2):客户端有多个,服务器有一个,在内核中,客户端和服务器的已经建立好的连接很多,应用程序在应用这些连接的时候,得一个一个进行处理.此时,内核就相当于队列,所建立的连接就相当于一个一个的待办事项.

  3):TCP的连接相当于多线程学过的生产者-消费者模型,一边生产一边进行消费.

     示意图如下:

   ①:当客户端和服务器尝试建立连接的时候,此时,服务器和客户端便会产生一系列的数据交互,这个称为"握手".

    ②:等"握手"这个过程完之后,此时,socket对象便会产生"管理连接"的队列,将客户端和服务器建立好的连接加入到队列中.

    ③:由应用程序从队列取一个一个的连接,即处理一个一个的待办事项.由socket对象调用accept这个静态方法,进行消费队列中的连接

二:TCP协议提供的API的静态方法和回显服务器

a:accept静态方法

b:回显服务器

服务器代码:
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TcpEchoServer {
    private ServerSocket serverSocket=null;
    private ExecutorService service= Executors.newCachedThreadPool();
    //在创建socket的同时,创建端口号
    public TcpEchoServer(int port) throws IOException {
        serverSocket=new ServerSocket(port);
    }
    //启动服务器
    public void start() throws IOException {
        System.out.println("启动服务器!");
        while(true){
            //1:处理客户端的连接,由于TCP是有连接的,服务器保存客户端的信息,客户端保存服务器的连接
            Socket clientSocket = serverSocket.accept();
            //通过上面产生的Socket对象和对方进行网络通信
//            Thread t=new Thread(()->{
//                try {
//                    processConnection(clientSocket);
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            });
//            t.start();
            service.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        processConnection(clientSocket);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
        }
    }
    //通过这个方法来处理一个连接的逻辑
    public void processConnection(Socket clientSocket) throws IOException {
        //通过这两个方法获取客户端的IP地址和端口号
        System.out.printf("[%s:%d] 客户端上线!\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());
        //接下来就可以读取请求,根据请求计算响应,返回响应三步走
        //Socket对象内部包含了两个字节流对象,就可以把这俩字节流对象获取到,完成后续的读写工作
        try(InputStream inputStream=clientSocket.getInputStream();
            OutputStream outputStream=clientSocket.getOutputStream();){
            //一次连接中,可能会涉及到多次请求.响应
            while(true){
                //1:读取请求并解析,为了读取方便,使用Scanner
                Scanner scanner=new Scanner(inputStream);
                if(!scanner.hasNext()){
                    //读取完毕,客户端下线
                    System.out.printf("[%s:%d] 客户端下线!\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());
                    break;
                }
                //客户端发过来的请求,是文本数据,同时,还得带有空白符  next:代表一直读,一直读到空白符(换行/回车/空格/制表符/翻页符)结束
                String  request=scanner.next();
                //2.根据请求计算响应
                String response = process(request);
                //3.把响应返回给客户端,
                PrintWriter writer=new PrintWriter(outputStream);
                //此处使用PrintWriter的println方法,把响应返回给客户端
                writer.println(response);
                writer.flush();//刷新缓冲区,提高程序的效率
                //日志:打印请求详情
                System.out.printf("[%s:%d] req:%s,resp:%s\n",clientSocket.getInetAddress().toString(),clientSocket.getPort(),request,response);
            }
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            clientSocket.close();
        }
    }
   public String process(String request){
        return request;
   }
    public static void main(String[] args) throws IOException {
       TcpEchoServer tcpEchoServer=new TcpEchoServer(9090);
       tcpEchoServer.start();
    }
}

TCP协议的回显服务器的服务器代码与UDP协议有部分区别,在TCP回显服务器的服务器代码中,主要分为连接+服务器代码必须步骤,下面,我将对TCP服务器端代码进行进一步详解,有问题的可以在底下留言.

  a:创建服务器对象

 

  b:手动设定服务器端口号

   

   c:启动服务器,即创建start方法,让服务器启动

      启动服务器,对当前日志进行打印

 

 

    d:客户端和服务器进行连接,调用ServerSocket对象的accept方法

   

           在前面的学习中,我们对于accept方法做出了详细的介绍,通过服务器的对象调用反悔了一个新的对象,小编认为返回的这个对象储存的是客户端的信息,包括客户端的IP地址和端口号.

  e:利用process方法对于客户端信息进行处理

 

processConnection方法内部代码解析:

1:读取从客户端发来的请求,服务端进行进一步解析

 2:根据第一步得到的字符解析,计算响应.
3:把响应返回给客户端

                                                    *****注意******

                          服务端是关闭客户端socket连接:防止资源的浪费

客户端代码
public class TcpEchoClient {
    private Socket socket=null;
    public TcpEchoClient(String serverIp,int serverport) throws IOException {
        //与完成了TCP客户端的建立,此时客户端通过new获得服务器的IP地址和端口号
        socket=new Socket(serverIp,serverport);
    }
    public void start(){
        System.out.println("客户端启动");
        Scanner scannerConsole=new Scanner(System.in);
        try(InputStream inputStream=socket.getInputStream();
            OutputStream outputStream=socket.getOutputStream()) {
            while(true){
              //1:从控制台输入一个字符串
                System.out.println("->");
                String request=scannerConsole.next();
              //2:构造请求,发送给服务器-->利用printWriter进行包装,将输出的进行打包,同时将从控制台输入的传递给服务器
                PrintWriter printWriter=new PrintWriter(outputStream);
                //使用println带上换行,后续服务器读取请求,就可以使用scanner.next来获取了
                printWriter.println(request);
                printWriter.flush();
                //3:从服务器读取响应,并进行处理
                Scanner scannerNetwork=new Scanner(inputStream);
                String respnse= scannerNetwork.next();
                //4:打印响应
                System.out.println(respnse);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws IOException {
      TcpEchoClient tcpEchoClient=new TcpEchoClient("127.0.0.1",9090);
      tcpEchoClient.start();
    }
}
1):客户端核心代码前准备

2):从控制台输入一个字符串

 

3):将从控制台输入的信息发送给服务器

4):从服务器读取响应,并进行打印

 


                                                ******注意*******

为了实现多客户端在同一服务器一起运行,并且互相不影响.此时我们需要多线程在服务器上来进行处理.

同时为了避免服务器的多次创建/销毁,所以我们可以利用线程池来解决.进一步节省了空间和时间.

 

 

 

相关文章
|
1月前
|
安全 网络安全 定位技术
网络通讯技术:HTTP POST协议用于发送本地压缩数据到服务器的方案。
总的来说,无论你是一名网络开发者,还是普通的IT工作人员,理解并掌握POST方法的运用是非常有价值的。它就像一艘快速,稳定,安全的大船,始终为我们在网络海洋中的冒险提供了可靠的支持。
79 22
|
1月前
|
网络协议 数据安全/隐私保护 网络架构
|
2月前
|
网络协议 物联网
VB6网络通信软件上位机开发,TCP网络通信,读写数据并处理,完整源码下载
本文介绍使用VB6开发网络通信上位机客户端程序,涵盖Winsock控件的引入与使用,包括连接服务端、发送数据(如通过`Winsock1.SendData`方法)及接收数据(利用`Winsock1_DataArrival`事件)。代码实现TCP网络通信,可读写并处理16进制数据,适用于自动化和工业控制领域。提供完整源码下载,适合学习VB6网络程序开发。 下载链接:[完整源码](http://xzios.cn:86/WJGL/DownLoadDetial?Id=20)
82 12
|
2月前
|
缓存 网络协议 API
掌握网络通信协议和技术:开发者指南
本文探讨了常见的网络通信协议和技术,如HTTP、SSE、GraphQL、TCP、WebSocket和Socket.IO,分析了它们的功能、优劣势及适用场景。开发者需根据应用需求选择合适的协议,以构建高效、可扩展的应用程序。同时,测试与调试工具(如Apipost)能助力开发者在不同网络环境下优化性能,提升用户体验。掌握这些协议是现代软件开发者的必备技能,对项目成功至关重要。
|
2月前
|
机器学习/深度学习 API Python
Python 高级编程与实战:深入理解网络编程与异步IO
在前几篇文章中,我们探讨了 Python 的基础语法、面向对象编程、函数式编程、元编程、性能优化、调试技巧、数据科学、机器学习、Web 开发和 API 设计。本文将深入探讨 Python 在网络编程和异步IO中的应用,并通过实战项目帮助你掌握这些技术。
|
3月前
|
人工智能 自然语言处理 决策智能
智能体竟能自行组建通信网络,还能自创协议提升通信效率
《一种适用于大型语言模型网络的可扩展通信协议》提出创新协议Agora,解决多智能体系统中的“通信三难困境”,即异构性、通用性和成本问题。Agora通过标准协议、结构化数据和自然语言三种通信格式,实现高效协作,支持复杂任务自动化。演示场景显示其在预订服务和天气预报等应用中的优越性能。论文地址:https://arxiv.org/pdf/2410.11905。
72 6
|
3月前
|
网络协议 测试技术 Linux
Golang 实现轻量、快速的基于 Reactor 模式的非阻塞 TCP 网络库
gev 是一个基于 epoll 和 kqueue 实现的高性能事件循环库,适用于 Linux 和 macOS(Windows 暂不支持)。它支持多核多线程、动态扩容的 Ring Buffer 读写缓冲区、异步读写和 SO_REUSEPORT 端口重用。gev 使用少量 goroutine,监听连接并处理读写事件。性能测试显示其在不同配置下表现优异。安装命令:`go get -u github.com/Allenxuxu/gev`。
|
5月前
|
负载均衡 网络协议 算法
不为人知的网络编程(十九):能Ping通,TCP就一定能连接和通信吗?
这网络层就像搭积木一样,上层协议都是基于下层协议搭出来的。不管是ping(用了ICMP协议)还是tcp本质上都是基于网络层IP协议的数据包,而到了物理层,都是二进制01串,都走网卡发出去了。 如果网络环境没发生变化,目的地又一样,那按道理说他们走的网络路径应该是一样的,什么情况下会不同呢? 我们就从路由这个话题聊起吧。
140 4
不为人知的网络编程(十九):能Ping通,TCP就一定能连接和通信吗?
|
5月前
|
前端开发 网络协议 安全
【网络原理】——HTTP协议、fiddler抓包
HTTP超文本传输,HTML,fiddler抓包,URL,urlencode,HTTP首行方法,GET方法,POST方法
|
5月前
|
网络协议
TCP报文格式全解析:网络小白变高手的必读指南
本文深入解析TCP报文格式,涵盖源端口、目的端口、序号、确认序号、首部长度、标志字段、窗口大小、检验和、紧急指针及选项字段。每个字段的作用和意义详尽说明,帮助理解TCP协议如何确保可靠的数据传输,是互联网通信的基石。通过学习这些内容,读者可以更好地掌握TCP的工作原理及其在网络中的应用。

热门文章

最新文章

OSZAR »