news 2026/5/16 1:53:45

网络协议TCP

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
网络协议TCP

网络编程TCP

TCP的核心特点:面向字节流(UDP是数据报),所有的读写的基本单位都是byte

ServerSocket:专门给服务器使用的,负责连接,不对数据进行操作

Socket:服务器和客户端都可以使用

当服务器启动的时候绑定端口号

因为TCP是有连接的,所以要使用accept去确保连接的开始

Socket要传入服务器的ip和端口号

因为TCP面向的是字节流,所以他没有向UDP数据报的那种sent和review方法,有的是字节流的读取(和之前文件IO很像)

TCPEchoServer

思路

实现TCPEchoServer,首先我们需要知道,所有的代码都是无法直接操作网卡的,一开始,我创建了一个serversocket类型的空变量,然后在构造方法中传入端口号,这个就相当于,我使用serversocket类这个代理人去帮我向操作系统申请一个小窗口,和网卡进行沟通,连接之后,因为serversocket只是连接,无法操作数据,所以就要使用socket来操作,然后在start方法中,首先我使用printf格式打印出来日志,然后因为TCP面向的是字节流,所以我不能向UDP那样使用数据报datagrampacket去进行操作,而是要使用inputstream和outputstream进行操作,这两个本来是需要使用read和write进行操作的,但是为了方便的情况下,我就使用scanner和printwrite进行套壳,然后因为我们这个是服务器,所以要在processconnecition方法中写内层一个死循环反复进行读取,然后当有输入的时候,使用一个string类型的去接收,接收到之后,就要进行处理,因为现在是回显式所以先不管,然后处理完响应只需要发回去就行,这个时候也有一个注意的地方,就是缓冲区,在java中,因为每次直接对网络或者文件进行修改太慢了,所有就会存在一个缓冲区,把你写的全部先存在一个地方,所以他并没有马上就传输出去,必须要等你使用flush把他冲走,他才会真的发送

具体实现

第一步

这一步首先就是创建一个空的serversocket类型的变量,然后在构造方法中初始化的时候传入使用的端口号,说人话就是你没办法直接操作网卡,所以要找serversocket这个代理人帮你和操作系统申请一个窗口,让你能够和网卡进行沟通

第二步

这一步首先就是打印日志,服务器启动,然后因为TCP是有连接的,所以我们需要先处理外层的连接,然后再去处理连接之后的事情,使用socket这个来处理文件的读取注意这个时候因为可能不只一个连接所以我们需要加入一个死循环确保可以支持多个客户端使用

第三步(核心)

这一步就是整个服务器最核心的地方了,首先当确立了连接之后,我们会记录日志,把对方的IP和端口号全部获取到,因为TCP协议是字节流的,所以这个时候就需要使用inputstream和outputstream这两个操作字节流,这里可以使用另外一种写法,每次读取一个数组的长度,读到-1就停止那种,但是就很麻烦,所以我们直接使用scanner和printwrite这两个更方便,只需要对inputstream和outputstream进行套个壳就行,套完壳之后就可以直接使用了。之后就很简单了,只要连接没断开就会一直等,后续的逻辑就是先读取请求,然后计算并返回响应,注意要刷新缓冲区,不然就会出现发不出去的情况,最后打印一下日志就结束。

源码

package NetWork; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; /** * Created with IntelliJ IDEA. * Description: * User: zhany * Date: 2025-12-15 * Time: 15:07 */ /*tcp协议的特点:有连接,面向字节流,全双工,可靠传输*/ public class TcpServerDemo { //首先,创建一个serversocket的空变量,Serversocket就是专门用来连接的 ServerSocket serverSocket = null; //初始化的同时指定端口号 public TcpServerDemo(int serverPort) throws IOException { serverSocket = new ServerSocket(serverPort); } //start方法 public void start() throws IOException { //首先,这个是服务器,所以需要24小时工作 System.out.println("服务器启动"); while(true){ //前面的serversocket任务已经结束,只负责连接不负责数据的修改,下面登场的是socket Socket clientSocket = serverSocket.accept(); //连接完就要负责处理数据了 Thread thread = new Thread(()->{ processconection(clientSocket); }); thread.start(); } } private void processconection(Socket clientSocket) { //先打印日志 System.out.printf("[%s,%d],客户端上线\n",clientSocket.getInetAddress(),clientSocket.getPort()); try(InputStream inputStream = clientSocket.getInputStream(); OutputStream outputStream = clientSocket.getOutputStream()) { while (true){ //字节流需要使用input和output //1.获取并解析连接 Scanner scanner = new Scanner(inputStream); PrintWriter writer = new PrintWriter(outputStream); if (!scanner.hasNext()){ System.out.printf("[%s,%d],客户端下线\n",clientSocket.getInetAddress(),clientSocket.getPort()); break; } String request = scanner.next(); //计算并返回 String response = process(request); writer.println(response); //刷新缓冲区 writer.flush(); } } catch (IOException e) { e.printStackTrace(); } finally { try { clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } private String process(String request) { return request; } public static void main(String[] args) throws IOException { TcpServerDemo tcpServerDemo = new TcpServerDemo(9090); tcpServerDemo.start(); } }

TcpEchoClient

思路

客户端的思路就比较简单,首先在构造方法中,需要初始化一下要去访问的服务器和端口号,然后在start方法中也是比较简单的,因为tcp是字节流的,所以需要直接使用inputstream和outputstream,直接使用套壳的scanner和printwrite会简单一些,不使用就要使用文件io的办法,然后在控制台读取用户的输入,然后发送给服务器,然后接受服务器的请求就可以了,注意这个也是要释放缓冲区的。

具体实现

第一步

Tcp中是提供构造方法让你可以直接输入网址的类似于127.0.0.1,在udp中要调用方法getname才行,这里初始化了要访问的ip和端口号

第二步

核心的start方法,这里就很简单了,因为TCP是字节流,所以他进行的操作也是需要使用inputstream和outputstream来进行操作的,使用scanner和printwrite进行套壳就不需要使用基础的文件io那种复杂的写法,然后只需要在控制台读取用户的输入,然后发送,接收返回值就行了

源码

package NetWork; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner; public class TcpClientDemo { private Socket socket; private static final String EXIT_CMD = "exit"; public TcpClientDemo(String serverIP, int serverPort) throws IOException { socket = new Socket(serverIP, serverPort); } public void start() { System.out.println("客户端启动"); System.out.println("输入内容发送到服务器(输入'exit'退出)"); try (InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); Scanner scanner = new Scanner(System.in); Scanner scannerNet = new Scanner(inputStream); PrintWriter writer = new PrintWriter(outputStream)) { while (true) { String request = scanner.nextLine(); if (EXIT_CMD.equalsIgnoreCase(request)) { break; } writer.println(request); writer.flush(); if (scannerNet.hasNextLine()) { String response = scannerNet.nextLine(); System.out.println("服务器响应: " + response); } } } catch (IOException e) { System.err.println("通信异常: " + e.getMessage()); } finally { try { if (socket != null && !socket.isClosed()) { socket.close(); } } catch (IOException e) { System.err.println("关闭socket异常: " + e.getMessage()); } } } public static void main(String[] args) { try { TcpClientDemo tcpClientDemo = new TcpClientDemo("127.0.0.1", 9090); tcpClientDemo.start(); } catch (IOException e) { System.err.println("连接服务器失败: " + e.getMessage()); } } }

上述的代码中,存在一个问题,就是多个客户端去访问的时候,会被卡住,阻塞在

因为当代码执行到确立连接之后,他就会往下走,跳到processconnection里面去,这个时候,后面的线程想要连接就必须等待前面的结束完才可以用

如何解决这个问题?

多线程这个时候就诞生了

只需要在在服务器里面加一个线程

这样就能实现让多线程去实现直接开启分身模式(小心超人上线)

但是每次都创建一个线程和销毁一个线程,开销的很大的,有没有更好的方法,有

线程池方法

在一开始就创建好n个线程,每当一个客户端来了就使用一下线程,这样就能最大限度使用服务器

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/8 22:42:33

重庆市大学生信息安全竞赛部分writeup

免责声明:本文章发布于比赛正式结束后,不存在提前泄露比赛信息及违规泄露wp的情况,作者不对读者基于本文内容而产生的任何行为或后果承担责任。如有任何侵权问题,请联系作者删除。 WEB5 传一句话木马,dirsearch扫出来…

作者头像 李华
网站建设 2026/5/13 23:38:40

数据有价可变现,华储数据助力解锁价值红利

近期,《数据有价 付费有为——加快培育为优质数据付费的市场意识》一文深刻指出,“为优质数据付费”是数据要素化、价值化、市场化的核心要求。站在数据提供方的视角,这一趋势释放了明确信号:优质数据绝非“沉没资产”&#xff0c…

作者头像 李华
网站建设 2026/5/9 0:50:49

Python 全面深入解析:从入门到精通

Python 全面深入解析:从入门到精通第一部分:Python 语言概述与哲学1.1 Python 的诞生与发展Python 由吉多范罗苏姆(Guido van Rossum)于1989年圣诞节期间在荷兰创建,最初作为 ABC 语言的替代品。1991年,Pyt…

作者头像 李华
网站建设 2026/5/10 16:17:48

一个完整的 Web 请求到底发生了什么

一、从输入一个网址开始 当我们在浏览器输入一个网址,然后按下回车,接下来浏览器显示了页面。网速好的话这之间可能就一秒,但在这一秒内到底发生了什么? 本文主要内容是试图记录一个完整 Web 请求的详细过程,从用户在…

作者头像 李华
网站建设 2026/5/10 10:06:33

JAVA中如何利用JSP实现大文件上传的验证机制?

大文件上传下载系统开发指南 项目概述 老哥,你这个需求可真是够硬核的!20G文件上传、文件夹层级保留、断点续传、加密传输存储,还要兼容IE8,预算才100块…这活儿不简单啊!不过既然你找到我了,咱们就一起啃…

作者头像 李华