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可以将网络中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
