【网络编程】TCP Socket编程

TCP Socket编程

  • 1. ServerSocket
  • 2. Socket
  • 3. TCP的长短连接
  • 4. Socket 通信模型
  • 5. 代码示例:TCP 回显服务器

流套接字: 使用传输层TCP协议
TCP: 即Transmission Control Protocol(传输控制协议),传输层协议。
TCP的特点:

  1. 有连接
  2. 可靠传输
  3. 面向字节流
  4. 有接收缓冲区,也有发送缓冲区
  5. 大小不限

1. ServerSocket

ServerSocket 是创建TCP服务端Socket的API。

注意: ServerSocket 只能用于 服务器端。

构造方法:

方法签名方法说明
ServerSocket(int port)创建一个服务端流套接字Socket,并绑定到指定端口

方法:

方法签名方法说明
Socket accept()开始监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端Socket对象,并基于该Socket建立与客户端的连接,否则阻塞等待
void close()关闭此套接字

2. Socket

Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。

构造方法:

方法签名方法说明
Socket(String host, int port)创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接

注意:这里面的 host 和 port 是要连接的服务器的 IP 地址和端口号。

方法:

方法签名方法说明
InetAddress getInetAddress()返回套接字所连接的地址
InputStream getInputStream()返回此套接字的输入流
OutputStream getOutputStream()返回此套接字的输出流

3. TCP的长短连接

TCP发送数据时,需要先建立连接,什么时候关闭连接就决定是短连接还是长连接:

短连接: 每次接收到数据并返回响应后,都关闭连接,即是短连接。也就是说,短连接只能一次收数据。
长连接: 不关闭连接,一直保持连接状态,双方不停的收发数据,即是长连接。也就是说,长连接可以多次收发数据。

两者区别如下:

  1. 建立连接、关闭连接的耗时:短连接每次请求、响应都需要建立连接,关闭连接;而长连接只需要第一次建立连接,之后的请求、响应都可以直接传输。相对来说建立连接,关闭连接也是要耗时的,长连接效率更高。
  2. 主动发送请求不同:短连接一般是客户端主动向服务端发送请求;而长连接可以是客户端主动发送请求,也可以是服务端主动发。
  3. 两者的使用场景有不同:短连接适用于客户端请求频率不高的场景,如浏览网页等。长连接适用于客户端与服务端通信频繁的场景,如聊天室,实时游戏等。

4. Socket 通信模型

在这里插入图片描述

5. 代码示例:TCP 回显服务器

服务器代码:

class TcpEchoServer {public ServerSocket serverSocket;//专门用来接受请求并建立链接public Socket clientSocket;//专门用来处理请求public TcpEchoServer(int port) throws IOException {this.serverSocket=new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动!");//也可以利用线程池ExecutorService threadsPool= Executors.newCachedThreadPool();while(true){//接受请求clientSocket=serverSocket.accept();
//            //利用多线程才能让服务器同时处理多个客户端的请求
//            Thread t=new Thread(()->{
//                //建立链接并处理请求
//                try {
//                    createConnection(clientSocket);
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            });
//            t.start();//创建线程池相对于每次创建一个线程来说效率更高一些threadsPool.submit(()->{try {createConnection(clientSocket);} catch (IOException e) {throw new RuntimeException(e);}});}}public void createConnection(Socket clientSocket) throws IOException {System.out.printf("[%s:%d]建立链接成功\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());//三个步骤//1.读取客户端请求(根据打开的文件流确定了读取的是客户端发来的请求)//这里针对TCP的读写和对于文件的读写是一摸一样的//利用socket构造文件流try(InputStream inputStream=clientSocket.getInputStream()){//注意打开的流//直接利用scanner读取(利用原生的InputStream也是可以的,但Scanner更方便)Scanner scanner=new Scanner(inputStream);try(OutputStream outputStream=clientSocket.getOutputStream()){//注意打开的流while(true){if(!scanner.hasNext()){System.out.printf("[%s:%d]断开链接\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());break;}//读取请求(TCP以字符流进行传输)// 读到空白符/ 空格/换行才会停止String request=scanner.next();//2.根据请求计算响应String response=process(request);//3.返回响应(根据打开的文件流决定了是往客户端返回请求)//为了方便用PrintWriter对OutputStream进行包裹PrintWriter printWriter=new PrintWriter(outputStream);// 因为使用 next,读到空白符/ 空格/换行才会停止,所以须使用 println printWriter.println(response);printWriter.flush();System.out.printf("[%d][req:%s resp:%s]\n",clientSocket.getPort(),request,response);}}}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();}
}

客户端代码:

class TcpEchoClient {public Socket client;//TCP中客户端构造函数的ip和port指的是要链接的服务器的IP和portpublic TcpEchoClient(String serverIp, int serverPort) throws IOException {this.client = new Socket(serverIp, serverPort);}public void start() throws IOException {System.out.println("和服务器建立链接成功");Scanner scanner = new Scanner(System.in);//这里针对TCP的读写和对于文件的读写是一摸一样的//利用socket构造文件流try (InputStream inputStream = client.getInputStream()) {try (OutputStream outputStream = client.getOutputStream()) {//接收从控制台输入的字符串while (true) {System.out.println("->");String request = scanner.next();//构造请求并发送请求(PrintWriter和Scanner对应)//注意文件流PrintWriter printWriter = new PrintWriter(outputStream);// 因为使用 next,读到空白符/ 空格/换行才会停止,所以须使用 println printWriter.println(request);printWriter.flush();//如果不及时刷新,服务器可能不能及时接收到数据//接收响应Scanner respScanner = new Scanner(inputStream);String response = respScanner.next();//显示到控制台上System.out.printf("[req:%s  resp:%s]\n", request, response);}}}}public static void main(String[] args) throws IOException {TcpEchoClient tcpEchoClient = new TcpEchoClient("127.0.0.1", 9090);tcpEchoClient.start();}
}

注意:当然要先启动服务器再启动客户端!

好啦! 以上就是对 TCP Socket编程的讲解,希望能帮到你 !
评论区欢迎指正 !

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/80135.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一文详解二叉搜索树

数据结构-二叉查找树 前言 **摘自百度百科:**二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若…

JDK8特性——接口增强函数式接口Optional方法引用

文章目录 接口增强默认方法静态方法 函数式接口SupplierConsumerFunctionPredicate Optional 类以前对null 的处理Optional的基本使用Optional的常用方法 方法引用方法引用的格式对象名::方法名类名::静态方法名类名::引用实例方法类名::构造器数组::构造器 接口增强 在JDK8之…

智能远程监考方案助力企业考试化繁为简

在音视频数字化之旅中,轻装上阵。 近年来,在数字化浪潮之下,远程考试频繁成为各领域热词,各企业也纷纷改革求新,将原本的企业内部考试转移到线上,从而获取更低廉的组考成本,更高的管理效率&…

深度学习基础之梯度下降

1. 引言 梯度下降是一种用于最小化(或最大化)损失函数的优化算法。它是机器学习和深度学习中的一个关键概念,通常用于调整学习算法中的参数。 梯度下降背后的核心思想是迭代调整参数以最小化损失函数。它的工作原理是计算损失函数相对于每个…

【LeetCode-中等题】18. 四数之和

文章目录 题目方法一:双指针(定2动2) 题目 方法一:双指针(定2动2) 这题可以参考【LeetCode-中等题】15. 三数之和 区别在于,三数之和只需要用一个for循环定住一个数,然后设置两个前…

数据结构与算法(C语言版)P4---顺序表、链表总结

顺序表和链表(双向带头链表)的区别 顺序表: 优点: 支持随机访问。需要随机访问结构支持算法可以很好的使用。cpu高速缓存利用率(命中率)更高。存储密度高 缺点: 头部中部插入删除时间效率低。…

合宙Air724UG LuatOS-Air LVGL API控件-窗口 (Window)

窗口 (Window) 分 享导出pdf 示例代码 win lvgl.win_create(lvgl.scr_act(), nil) lvgl.win_set_title(win, "Window title") -- close_btn lvgl.win_add_btn_right(win, "\xef\x80\x8d") -- --lvgl.obj_set_event_cb(cl…

典型数据结构-图,图的存储、基本操作和遍历

图 引自:《数据结构教程》。 概念 图可以使得元素之间的关系是 多对多。图中任意两个数据元素之间都可能存在连接关系。图作为一种数据结构,可以表达数据元素之间广泛存在着的更为复杂的关系。在众多应用之中,如电子线路分析、工程计划分析、…

Junit单元测试异常处理方法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 Junit单元测试异常处理方法 前言案例准备一、类方法内处理异常二、测试方法中处理异常1.try/catch/finally 语句2.Test(expected)3.ExpectedException 前言 提示&#xff1a…

深度解析shell脚本的命令的原理之mv

mv 是 Unix 或 Linux 中的一个基本命令,用于移动或重命名文件和目录。以下是对这个命令的深度解析: 基本操作:mv 命令的基本操作是将一个或多个源文件或目录移动到一个目标文件或目录,或者重命名源文件或目录。这是通过改变文件系…

银河麒麟--国产操作系统-九五小庞

那么,我国国产操作系统现状到底如何呢? 自 1999 年徐冠华部长一语点破我们的产业软肋之后,国产操作系统起步于国家“七五”计划期间,目前国产操作系统均是基于Linux内核进行的二次开发,中国国产操作系统进入Linux元年…

CSS:隐藏移动端的滚动条的方式

目录 方式一:-webkit-scrollbar方式二:overflow方式三:clip-path方式四:mask 遮罩总结参考 移动端开发中,有一个横向滚动元素,产品告诉我不需要滚动条,我说这个简单,隐藏一下不就行了…

iText实战--在现有PDF上工作

6.1 使用PdfReader读取PDF 检索文档和页面信息 D:/data/iText/inAction/chapter03/image_direct.pdf Number of pages: 1 Size of page 1: [0.0,0.0,283.0,416.0] Rotation of page 1: 0 Page size with rotation of page 1: Rectangle: 283.0x416.0 (rot: 0 degrees) Is reb…

深度思考ES面经

1 推荐文章 2万字详解,吃透 Elasticsearch 2 什么是倒排索引,为什么这么叫? 倒排索引(Inverted Index)是一种为快速全文搜索而设计的数据结构。它被广泛应用于搜索引擎,其中 Elasticsearch(简…

C# 扫描并读取图片中的文字(.NET Core)

本文介绍如何通过C# 程序来扫描并读取图片中的文字,这里以创建一个.Net Core程序为例。下面是具体步骤,供参考。 程序测试环境: Visual Studio版本要求不低于2017 图片扫描工具:Spire.OCR for .NET 图片格式:png&…

JSP ssm 网上求职管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 JSP ssm 网上求职管理系统是一套完善的web设计系统(系统采用SSM框架进行设计开发,springspringMVCmybatis),对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采…

zookeeper最基础教程

文章目录 一、简介1、工作机制2、特点3、数据结构4、应用场景5、选举机制 二、软件安装1、单机版安装2、集群安装3、配置参数解读(zoo.cfg)4、ZK集群启动脚本 三、命令行操作1、语法2、使用3、节点相关4、监听器原理5、节点删除与查看 三、写数据流程 一、简介 1、工作机制 官…

SQL优化--排序优化(order by)

Using filesort : 通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sort buffer中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。 Using index : 通过有序索引顺序扫描直接返回有序数据&#xff0c…

1031. 两个非重叠子数组的最大和

1031. 两个非重叠子数组的最大和 原题链接:完成情况:解题思路:参考代码: 原题链接: 1031. 两个非重叠子数组的最大和 https://leetcode.cn/problems/maximum-sum-of-two-non-overlapping-subarrays/description/ 完…

【C语言】指针的进阶(一)

目录 前言 1. 字符指针 2. 指针数组 3. 数组指针 3.1 数组指针的定义 3.2 &数组名VS数组名 3.3 数组指针的使用 4. 数组参数、指针参数 4.1 一维数组传参 4.2 二维数组传参 4.3 一级指针传参 4.4 二级指针传参 5. 函数指针 前言 指针在C语言中可谓是有着举足轻重的…