Socket编程中关于服务器端监听端口与新连接端口的深入剖析
Socket编程中关于服务器端监听端口与新连接端口的深入剖析
在Socket编程领域,存在一个容易让初学者感到困惑的问题。尽管很多人在网络上进行了相关探讨,但不少解释要么不够清晰明了,要么太过肤浅,未能深入到问题的核心,这使得初学者在理解上存在诸多障碍。
其中一个关键问题是:当Socket的服务端监听一个固定端口(例如8888),客户端前来连接此端口后,服务器会生成一个新的Socket与对应的客户端进行通讯。那么,这个新的Socket的发送和接收端口究竟是怎样的呢?是随机分配的,还是依然为8888?在此,明确地告诉读者,答案是8888。即所有由该监听产生的回应客户端的新Socket,其收发数据所使用的端口都是8888。后续将通过代码实现以及网络命令的展示来进一步验证这一点。
代码实现
服务端代码
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")#define DEFAULT_PORT "8888"
#define DEFAULT_BUFLEN 1024int main() {// 1. 初始化 WinsockWSADATA wsaData;int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iResult!= 0) {std::cerr << "WSAStartup failed: " << iResult << std::endl;return 1;}// 2. 创建套接字SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (ListenSocket == INVALID_SOCKET) {std::cerr << "Socket creation failed: " << WSAGetLastError() << std::endl;WSACleanup();return 1;}// 3. 绑定套接字到本地地址和端口sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = INADDR_ANY;serverAddr.sin_port = htons(atoi(DEFAULT_PORT));iResult = bind(ListenSocket, (sockaddr*)&serverAddr, sizeof(serverAddr));if (iResult == SOCKET_ERROR) {std::cerr << "Bind failed: " << WSAGetLastError() << std::endl;closesocket(ListenSocket);WSACleanup();return 1;}// 4. 监听连接请求iResult = listen(ListenSocket, SOMAXCONN);if (iResult == SOCKET_ERROR) {std::cerr << "Listen failed: " << WSAGetLastError() << std::endl;closesocket(ListenSocket);WSACleanup();return 1;}std::cout << "Server is listening on port " << DEFAULT_PORT << "..." << std::endl;do {// 5. 接受客户端连接SOCKET ClientSocket = accept(ListenSocket, NULL, NULL);if (ClientSocket == INVALID_SOCKET) {std::cerr << "Accept failed: " << WSAGetLastError() << std::endl;closesocket(ListenSocket);WSACleanup();return 1;}// 6. 接收和发送数据char recvbuf[DEFAULT_BUFLEN];int recvbuflen = DEFAULT_BUFLEN;iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);if (iResult > 0) {recvbuf[iResult] = '\0';std::cout << "Received from client: " << recvbuf << std::endl;const char* sendbuf = "Hello from server!";iResult = send(ClientSocket, sendbuf, strlen(sendbuf), 0);if (iResult == SOCKET_ERROR) {std::cerr << "Send failed: " << WSAGetLastError() << std::endl;}} else if (iResult == 0) {std::cout << "Connection closing..." << std::endl;} else {std::cerr << "Recv failed: " << WSAGetLastError() << std::endl;}} while (1);// 7. 关闭套接字//closesocket(ClientSocket);closesocket(ListenSocket);WSACleanup();return 0;
}
这段服务端代码首先进行Winsock的初始化,接着创建套接字、绑定到指定端口(8888)、开始监听连接请求。在接受客户端连接后,能够接收客户端发送的数据,并向客户端发送响应信息。
客户端代码
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")#define DEFAULT_PORT "8888"
#define DEFAULT_BUFLEN 1024
#define SERVER_ADDR "127.0.0.1"int main() {// 1. 初始化 WinsockWSADATA wsaData;int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iResult!= 0) {std::cerr << "WSAStartup failed: " << iResult << std::endl;return 1;}// 2. 创建套接字SOCKET ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (ConnectSocket == INVALID_SOCKET) {std::cerr << "Socket creation failed: " << WSAGetLastError() << std::endl;WSACleanup();return 1;}// 3. 配置服务器地址结构体sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = inet_addr(SERVER_ADDR);serverAddr.sin_port = htons(atoi(DEFAULT_PORT));// 4. 连接服务器iResult = connect(ConnectSocket, (sockaddr*)&serverAddr, sizeof(serverAddr));if (iResult == SOCKET_ERROR) {std::cerr << "Connect failed: " << WSAGetLastError() << std::endl;closesocket(ConnectSocket);WSACleanup();return 1;}std::cout << "Connected to server " << SERVER_ADDR << ":" << DEFAULT_PORT << std::endl;// 5. 发送数据const char* sendbuf = "Hello from client!";iResult = send(ConnectSocket, sendbuf, strlen(sendbuf), 0);if (iResult == SOCKET_ERROR) {std::cerr << "Send failed: " << WSAGetLastError() << std::endl;closesocket(ConnectSocket);WSACleanup();return 1;}// 6. 接收服务器响应char recvbuf[DEFAULT_BUFLEN];int recvbuflen = DEFAULT_BUFLEN;iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);if (iResult > 0) {recvbuf[iResult] = '\0';std::cout << "Received from server: " << recvbuf << std::endl;} else if (iResult == 0) {std::cout << "Connection closing..." << std::endl;} else {std::cerr << "Recv failed: " << WSAGetLastError() << std::endl;}getchar();// 7. 关闭套接字closesocket(ConnectSocket);WSACleanup();return 0;
}
客户端代码同样先进行Winsock的初始化,创建套接字后,配置服务器地址并尝试连接到服务器(地址为127.0.0.1,端口8888)。连接成功后,发送数据给服务器并接收服务器的响应。
网络命令验证
使用Windows下的VC++对上述代码进行编译链接,生成socket_server.exe和socket_client.exe程序。
- 首先运行
socket_server.exe程序,此时网络监听情况如下,服务进程PID:18076
C:\Users\hss>netstat -ano | findstr :8888
TCP 0.0.0.0:8888 0.0.0.0:0 LISTENING 18076
可以看到服务端在8888端口处于监听状态,进程ID为18076。
- 接着分别运行2个客户端
socket_client.exe程序,网络监听和连接情况如下:
C:\Users\hss>netstat -ano | findstr :8888
TCP 0.0.0.0:8888 0.0.0.0:0 LISTENING 18076
TCP 127.0.0.1:8888 127.0.0.1:35582 ESTABLISHED 18076
TCP 127.0.0.1:8888 127.0.0.1:35634 ESTABLISHED 18076
TCP 127.0.0.1:35582 127.0.0.1:8888 ESTABLISHED 5896
TCP 127.0.0.1:35634 127.0.0.1:8888 ESTABLISHED 22044
从上述结果可以清晰地看出,服务器进程(ID为18076)有1个监听的8888端口和2个与客户端建立的TCP连接,且这些连接的本地收发端口都是8888。而客户端有2个进程(ID分别为8896和22044),它们的端口是随机分配的(分别是35582和35634)。
通过以上的代码实现和网络命令验证,足以证明服务器监听返回的新的Socket链接的收发数据端口都是监听端口8888。这对于深入理解Socket编程中的端口使用机制具有重要意义,能够帮助初学者更加准确地把握网络编程中这一关键知识点,从而在后续的编程实践中避免因端口概念不清而产生的错误和困惑,提升编程的准确性和效率,为进一步深入学习网络编程奠定坚实的基础。
相关文章:
Socket编程中关于服务器端监听端口与新连接端口的深入剖析
Socket编程中关于服务器端监听端口与新连接端口的深入剖析 在Socket编程领域,存在一个容易让初学者感到困惑的问题。尽管很多人在网络上进行了相关探讨,但不少解释要么不够清晰明了,要么太过肤浅,未能深入到问题的核心࿰…...
如何通过HTTP API更新Doc
本文介绍如何通过HTTP API更新Collection中已存在的Doc。 说明 若更新Doc时指定id不存在,则本次更新Doc操作无效 如只更新部分属性fields,其他未更新属性fields默认被置为null 前提条件 已创建Cluster:创建Cluster。 已获得API-KEY&#…...
Qt5 中 QGroupBox 标题下沉问题解决
我们设置了QGroupBox 样式之后,发现标题下沉了,那么如何解决呢? QGroupBox {font: 12pt "微软雅黑";color:white;border:1px solid white;border-radius:6px; } 解决后的效果 下面是解决方法: QGroupBox {font: 12pt "微软雅黑";color:white;bo…...
[OpenGL]使用glsl实现smallpt
一、简介 本文介绍了如何使用 OpenGL,使用 glsl 语言在 Fragment shader 中实现 smallpt。程序完成后可以得到以下渲染结果(samples per pixel, spp 16)。在程序中按下A,W可以左右平移,按下W,S可以前后平移: 二、s…...
elementui的默认样式修改
今天用element ui ,做了个消息提示,发现提示的位置总是在上面,如图: 可是我想让提示的位置到下面来,该怎么办? 最后还是看了官方的api 原来有个自定义样式属性 customClass 设置下就好了 js代码 css代码…...
mysql的主从配置
#mysql数据库 #主从 MySQL数据库主从配置 1.MySQL主从介绍 MySQL 主从又叫做 Replication、AB 复制。简单讲就是 A 和 B 两台机器做主 从后,在 A 上写数据,另外一台 B 也会跟着写数据,两者数据实时同步的。 MySQL 主从是基于 binlog 的&…...
CPO-CNN-GRU-Attention、CNN-GRU-Attention、CPO-CNN-GRU、CNN-GRU四模型多变量时序预测对比
CPO-CNN-GRU-Attention、CNN-GRU-Attention、CPO-CNN-GRU、CNN-GRU四模型多变量时序预测对比 目录 CPO-CNN-GRU-Attention、CNN-GRU-Attention、CPO-CNN-GRU、CNN-GRU四模型多变量时序预测对比预测效果基本介绍程序设计参考资料 预测效果 基本介绍 基于CPO-CNN-GRU-Attention、…...
深入了解PINN:物理信息神经网络(Physics-Informed Neural Networks)
1. 什么是PINN(物理信息神经网络)? 物理信息神经网络(PINN,Physics-Informed Neural Networks)是一类通过结合神经网络和物理方程的深度学习方法。其主要特点是将物理系统的约束条件(如偏微分方…...
人形机器人全身运动规划相关资料与文章
1.HumanPlus: Humanoid Shadowing and Imitation from Humans 文章地址:[2406.10454] HumanPlus: Humanoid Shadowing and Imitation from Humans 代码地址:MarkFzp/humanplus: [CoRL 2024] HumanPlus: Humanoid Shadowing and Imitation from Humans …...
使用uWSGI将Flask应用部署到生产环境
使用uWSGI将Flask应用部署到生产环境: 1、安装uWSGI conda install -c conda-forge uwsgi(pip install uwsgi会报错) 2、配置uWSGI 在python程序的同一文件夹下创建 uwsgi.ini文件,文件内容如下表。 需要按照实际情况修改文件名称…...
微服务监控工具Grafana
目录 前言 服务介绍 Grafana:数据可视化和展示 Prometheus:时序数据监控 Loki:日志管理 工具使用 安装 配置 Grafana 数据源编辑 Go Web 项目上报数据 Prometheus 指标上报 Loki 日志上报 数据查看 前言 随着微服务的盛行&…...
用户界面的UML建模06
4.1 抽象表示层的结构(Abstract Presentation Structure) 如图6 所示,抽象表示层模型具有一个顶层的容器(container),《apm》AbstractForm,其包含了许多组件,《apm》AbstractCompon…...
【力扣刷题第一天】63.不同路径Ⅱ
63.不同路径Ⅱ 🚀 题目 题目来源:leetcode 63. 不同路径Ⅱ:63. 不同路径 II - 力扣(LeetCode); 给定一个 m x n 的整数数组 grid。一个机器人初始位于 左上角(即 obstacleGrid[0][0]…...
如何优化Python网络爬虫的数据清洗流程,以提升数据质量并有效应对网站反爬虫机制?
优化爬虫数据清洗流程,应对反爬虫机制 一、数据清洗的重要性 在网络爬虫中,数据清洗是关键环节。打个比方,我们从网页抓取到的原始数据就像一堆杂乱的杂物,里面有各种格式、错误和重复信息。比如抓取到的文本可能包含HTML标签、…...
svn 相关应用与管理
文章目录 SVN 概要svn 权限控制svn 实操实例svn 备份 SVN 概要 一、SVN简介 Subversion(SVN)是一个开放源代码的版本控制系统,用于管理文件和目录的版本。它采用集中式的版本控制方式,即有一个中央仓库存储所有文件的版本信息&a…...
THM:Mouse Trap[WriteUP]
目录 连接至THM服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 提取扫描结果中的端口号 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机UDP常用端口进行开放扫描 使用smbmap尝试枚举靶机…...
Nginx详细安装配置过程
目录 1.nginx环境准备 1.1 在配置好yum源之后,安装如下的编译工具 1.2 安装nginx所需的依赖库 1.3 关闭防火墙,selinux,并确保网络正常 2.nginx的编译安装 2.1从nginx官网复制下载链接,wget 下载 2.2? 解压nginx源代码 2…...
目标检测入门指南:从原理到实践
目录 1. 数据准备与预处理 2. 模型架构设计 2.1 特征提取网络原理 2.2 区域提议网络(RPN)原理 2.3 特征金字塔网络(FPN)原理 2.4 边界框回归原理 2.5 非极大值抑制(NMS)原理 2.6 多尺度训练与测试原理 2.7 损失函数设计原理 3. 损失函数设计 4. 训练策略优化 5. 后…...
2024 高通边缘智能创新应用大赛智能边缘计算赛道冠军方案解读
2024 高通边缘智能创新应用大赛聚焦不同细分领域的边缘智能创新应用落地,共设立三大热门领域赛道——工业智能质检赛道、智能边缘计算赛道和智能机器人赛道。本文为智能边缘计算赛道冠军项目《端侧大模型智能翻译机》的开发思路与成果分享。 赛题要求 聚焦边缘智能…...
tcpdump 网络数据包分析工具
简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具。 tcpdump可以将网络中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
uniapp 小程序 学习(一)
利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 :开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置,将微信开发者工具放入到Hbuilder中, 打开后出现 如下 bug 解…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...
