Day2:Windows网络编程-TCP
今天开始进入Windows网络编程的学习,在学习的时候总是陷入Windows复杂的参数,纠结于这些。从老师的讲解中,这些内容属于是定式,主要学习写的逻辑。给自己提个醒,要把精力放在正确的位置,不要无端耗费精力。
关于C/S模式
C:Client 客户端:
- 打开一个通信通道,并连接到服务器所在主机的特定端口
- 向服务器发服务请求,等待并接收应答,继续提出请求
- 请求结束后关闭通信通道并终止
S:Server 服务端:
- 首先服务器先启动,并根据请求提供相应的服务
- 打开一个通信通道,在某一地址和端口上接收请求
- 等待客户请求到达该端口
- 接收到服务请求,处理该请求并发送应答信号
- 返回第二步,等待另一客户请求
- 关闭服务器
关于TCP与UDP
TCP:面向连接的套接字
- 传输过程中数据不会丢失
- 按顺序传输数据
- 传输的过程中不存在数据边界
UDP:面向消息的套接字
- 强调快速传输而非顺序
- 传输的数据可能丢失也可能损毁
- 限制每次传输数据的大小
- 传输的数据由数据边界
关于IP
是分配给用户上网使用的网际协议
常见的IP地址分为IPv4与IPv6两大类两大类
关于端口
为区分程序中创建的套接字而分配给套接字的序号
不同的端口对应不同的应用程序
端口有65536之多
关于套接字类型与协议设置
SOCK_STREAM 对应TCP协议
SOCK_DGRAM 对应UDP
SOCK_RAW 可以读写内核没有处理的IP数据包,避开 TCP/IP 处理机制,被传送的数据报可以被直接传送给需要它的的应用程序
关于网络编程的基本函数和基本数据结构

两个重要的数据结构:
struct sockaddr {u_short sa_family; //16 位地址类型 2 字节char sa_data[14]; //14 字节地址数据:ip + port
};
struct sockaddr_in {short sin_family; //16 位地址类型u_short sin_port; //16 位端口号 65535 2 的 16 次方struct in_addr sin_addr; //32 位 IP 地址 4 字节char sin_zero[8]; //8 字节填充
};
TCP 套接字

TCP Server
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>// error LNK2019: 无法解析的外部符号 __imp__accept@12,函数 _main 中引用了该符号
#pragma comment(lib,"ws2_32.lib") // 导入库int main()
{printf("TCP Server\n");// 0. 初始化网络库 加载套接字库 这是个标准做法,直接拷贝即可WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD(2, 2);// 1、初始化套接字库err = WSAStartup(wVersionRequested, &wsaData);if (err != 0){printf("WSAStartup errorNum = %d\n", GetLastError());return err;}if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){printf("LOBYTE errorNum = %d\n", GetLastError());WSACleanup();return -1;}// 1. 安装电话机// AF_INET指定了使用 IPv4 地址和 TCP/IP 协议栈进行网络通信。// 用于指定套接字的类型,表示基于流的传输协议,常用于 TCP 协议的网络通信。// 第三个参数由前两个决定。// 光标放在socket()函数上,摁下F1,转到官方文档SOCKET sockSrv = socket(AF_INET,SOCK_STREAM,0); //socket 函数创建一个绑定到特定传输服务提供者的套接字。if (INVALID_SOCKET == sockSrv){printf("socket errorNum = %d\n", GetLastError());return -1;}// 2. 分配电话号码,填充参数SOCKADDR_IN addSrv; // SOCKADDR_IN结构指定 AF_INET 地址系列的传输地址和端口。// 设置为任何IPaddSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);addSrv.sin_family = AF_INET;addSrv.sin_port = htons(6000);// 根据官方文档,这里需要强转 if (SOCKET_ERROR == bind(sockSrv, (SOCKADDR*)&addSrv, sizeof(SOCKADDR))) // 绑定函数将本地地址与套接字相关联。{printf("bind errorNum = %d\n", GetLastError());return -1;}// 3. 监听 listen// 将套接字置于侦听传入连接的状态。if (SOCKET_ERROR == listen(sockSrv, 5)){printf("listen errorNum = %d\n", GetLastError());return -1;}SOCKADDR_IN addrCli;int len = sizeof(SOCKADDR);while (true){// 4.分配一台分机去处理客户端的连接printf("begin accept: \n");SOCKET sockConn = accept(sockSrv,(SOCKADDR*)&addrCli,&len);printf("end accept: \n");char sendBuf[100] = { 0 };sprintf_s(sendBuf, 100, "Welcome %s to bingo!",inet_ntoa(addrCli.sin_addr));int iLen = send(sockConn,sendBuf,strlen(sendBuf),0);char recvBuf[100] = { 0 };iLen = recv(sockConn, recvBuf, 100, 0);printf("recvBuf = %s\n", recvBuf);// 关闭分机closesocket(sockConn);}// 关闭总机closesocket(sockSrv);WSACleanup();system("pause");return 0;
}
TCP Client
代码如下:
#include <WinSock2.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "ws2_32.lib")int main()
{printf("Client\n");char sendBuf[] = "hello,world";//1 初始化网络库// 加载套接字库WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD(2, 2);// 1、初始化套接字库err = WSAStartup(wVersionRequested, &wsaData);if (err != 0){printf("WSAStartup errorNum = %d\n", GetLastError());return err;}if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){printf("LOBYTE errorNum = %d\n", GetLastError());WSACleanup();return -1;}// 2 安装电话机// 新建套接字SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0);if (INVALID_SOCKET == sockCli){printf("socket errorNum = %d\n", GetLastError());return -1;}SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr = inet_addr("10.134.142.81");addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(6000);// 3 连接服务器if (SOCKET_ERROR == connect(sockCli, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR))){printf("connect errorNum = %d\n", GetLastError());return -1;}// 4 接收和发送数据char recvBuf[100] = { 0 };int iLen = recv(sockCli, recvBuf, 100, 0);if (iLen < 0){printf("recv errorNum = %d\n", GetLastError());return -1;}printf("Client recvBuf = %s\n", recvBuf);// 发送数据iLen = send(sockCli, sendBuf, strlen(sendBuf) + 1, 0);if (iLen < 0){printf("send errorNum = %d\n", GetLastError());return -1;}// 关闭套接字closesocket(sockCli);WSACleanup();system("pause");return 0;
}// 报错:严重性 代码 说明 项目 文件 行 禁止显示状态
// 错误 C4996 'inet_addr': Use inet_pton() or InetPton() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings TCP Client C : \Users\mi\Desktop\Code - C++\MyNetPro\TCP Client\TCP Client.cpp 38
// 我们需要把它 _WINSOCK_DEPRECATED 忽略掉 工程属性 C++预处理器添加即可
结果如下:

关于Listen()
listen(sockSrv,5):这个函数是规定了消息队列,最多可以有五个,后面再来的消息会来连接不上。
关于VS的启动项
设置哪个为启动项就会编译那个过程的C++文件

关于报错: _WINSOCK_DEPRECATED
// 报错:严重性 代码 说明 项目 文件 行 禁止显示状态
// 错误 C4996 'inet_addr': Use inet_pton() or InetPton() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings TCP Client C : \Users\mi\Desktop\Code - C++\MyNetPro\TCP Client\TCP Client.cpp 38
// 我们需要把它 _WINSOCK_DEPRECATED 忽略掉 工程属性 C++预处理器添加即可
优化recv与send,解决超大数据传输问题
接收端:
int MySocketRecv0(int sock, char* buf, int dateSize)
{//循环接收int numsRecvSoFar = 0; // 目前受到的数据int numsRemainingToRecv = dateSize; // 剩余要收的数据printf("enter MySocketRecv0\n");while (1){int bytesRead = recv(sock, &buf[numsRecvSoFar], numsRemainingToRecv, 0);printf("###bytesRead = %d,numsRecvSoFar = %d, numsRemainingToRecv = %d\n",bytesRead, numsRecvSoFar, numsRemainingToRecv);if (bytesRead == numsRemainingToRecv) // 一次性完全接收{return 0;}else if (bytesRead > 0) // 未接收完,更新已接受数据和未接受数据{numsRecvSoFar += bytesRead;numsRemainingToRecv -= bytesRead;continue;}else if ((bytesRead < 0) && (errno == EAGAIN)){continue;}else{return -1;}}
}
发送端:
int MySocketSend0(int socketNum, unsigned char* data, unsigned dataSize)
{unsigned numBytesSentSoFar = 0;unsigned numBytesRemainingToSend = dataSize;while (1){int bytesSend = send(socketNum, (char const*)(&data[numBytesSentSoFar]),numBytesRemainingToSend, 0/*flags*/);if (bytesSend == numBytesRemainingToSend){return 0;}else if (bytesSend > 0){numBytesSentSoFar += bytesSend;numBytesRemainingToSend -= bytesSend;continue;}else if ((bytesSend < 0) && (errno == 11)){continue;}else{return -1;}}
}
相关文章:
Day2:Windows网络编程-TCP
今天开始进入Windows网络编程的学习,在学习的时候总是陷入Windows复杂的参数,纠结于这些。从老师的讲解中,这些内容属于是定式,主要学习写的逻辑。给自己提个醒,要把精力放在正确的位置,不要无端耗费精力。…...
leetcode1985. 找出数组中的第 K 大整数
给你一个字符串数组 nums 和一个整数 k 。nums 中的每个字符串都表示一个不含前导零的整数。 返回 nums 中表示第 k 大整数的字符串。 注意:重复的数字在统计时会视为不同元素考虑。例如,如果 nums 是 ["1","2","2"]&am…...
基于深度学习的高精度野生动物检测识别系统(PyTorch+Pyside6+YOLOv5模型)
摘要:基于深度学习的高精度野生动物检测(水牛、犀牛、斑马和大象)识别系统可用于日常生活中或野外来检测与定位野生动物目标,利用深度学习算法可实现图片、视频、摄像头等方式的野生动物目标检测识别,另外支持结果可视…...
从零开始 Spring Boot 35:Lombok
从零开始 Spring Boot 35:Lombok 图源:简书 (jianshu.com) Lombok是一个java项目,旨在帮助开发者减少一些“模板代码”。其具体方式是在Java代码生成字节码(class文件)时,根据你添加的相关Lombok注解或类来…...
深入解析Spring源码系列:Day 6 - Spring MVC原理
深入解析Spring源码系列:Day 6 - Spring MVC原理 欢迎来到本系列的第六篇博客。在前几篇博客中,我们探索了Spring框架的核心概念,包括Bean的生命周期、作用域、AOP原理和事务管理。今天,我们将深入研究Spring框架中的MVC…...
Cmake中message函数 如何优雅地输出
message函数说明 在CMake中,message()函数用于向终端输出信息。 message([<mode>] "message text" ...)函数的<mode>参数可以是以下之一: (none): 等同于STATUS,但不推荐使用。STATUS: 输出的信息会被发送到CMake的…...
人工智能基础部分20-生成对抗网络(GAN)的实现应用
大家好,我是微学AI,今天给大家介绍一下人工智能基础部分20-生成对抗网络(GAN)的实现应用。生成对抗网络是一种由深度学习模型构成的神经网络系统,由一个生成器和一个判别器相互博弈来提升模型的能力。本文将从以下几个方面进行阐述࿱…...
JavaScript表单事件(上篇)
目录 一、input: 当表单元素的值发生改变时触发,适用于大多数表单元素。 二、change: 当表单元素的值发生改变且失去焦点时触发,适用于输入框、下拉列表等。 三、submit: 当表单提交时触发,适用于 form 元素。 四、reset: 当表单重置时触…...
vb6 Webview2微软Edge Chromium内核执行JS取网页数据测速
微软Edge Chromium内核执行JS获取网页数据测试 ExcuteScript eval(document.body.innerHTML) from : https://www.163.com 采集的网页HTM字符串占用字节空间1.2MB ExcuteScript回调事件中取得JS执行结果,用时 54 毫秒 其中JSON转字符13.5209毫秒 jSON数据长度: 增…...
编码,Part 1:ASCII、汉字及 Unicode 标准
个人博客 编码的历史由来就懒得介绍了,只需要知道人类处理文本信息是以字符为基本单位,而计算机在最底层只认识 0/1,所以当计算机要为人类存储/呈现字符时,就需要有一个规则,在字符和 0/1 序列之间建立映射关系&#…...
C++ Eigen库矩阵操作
C Eigen库 序号功能例子1赋值Eigen::MatrixXf mat (12,1); \\% mat << 1, 2, 3, 4,5,6,7,8,9,10,11,12;2Inplace操作 \\% resizemat.resize(4, 3); \\% 1 5 9 \\% 2 6 10 \\% 3 7 11 \\% 4 8 123转置 \\% transposeInPlacemat.transposeInPlace(); \\% 1 2 3 4 \\% 5…...
Linux-0.11 boot目录bootsect.s详解
Linux-0.11 boot目录bootsect.s详解 模块简介 bootsect.s是磁盘启动的引导程序,其概括起来就是代码的搬运工,将代码搬到合适的位置。下图是对搬运过程的概括,可以有个印象,后面将详细讲解。 bootsect.s主要做了如下的三件事: 搬…...
django组件552
前言:相信看到这篇文章的小伙伴都或多或少有一些编程基础,懂得一些linux的基本命令了吧,本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python:一种编程语言&…...
【枚举算法的Java实现及其应用】
文章目录 枚举算法概述枚举算法的实现步骤Java实现枚举算法枚举算法的底层工作原理枚举算法的底层代码讲解枚举算法的实际应用场景枚举算法在场景中解决的问题总结 枚举算法概述 枚举算法是一种通过列举所有可能情况来解决问题的方法。这种算法在解决一些特定类型的问题时非常…...
linux led 驱动
前言 今天是儿童节,挣个奖牌给小孩玩玩。 在 linux 驱动大家庭中,LED 驱动算是个儿童,今天就写写他吧。正好之前写过他的婴儿时期《i.MX6ULL 裸机点亮 LED》,记得那时候他还穿着开裆裤呢,裸鸡嘛。 ioremap() 裸机程…...
平面最近点对(分治算法)
文章目录 平面最近点对(分治算法)Solution流程完整模板代码 平面最近点对(分治算法) 文章首发于我的个人博客:欢迎大佬们来逛逛 平面最近点对(加强版) - 洛谷 给你一些点,求两点之…...
【基于前后端分离的博客系统】Servlet版本
🎉🎉🎉点进来你就是我的人了博主主页:🙈🙈🙈戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔🤺🤺🤺 目录 一. 项目简介 1. 项目背景 2. 项目用到的技…...
在线Excel绝配:SpreadJS 16.1.1+GcExcel 6.1.1 Crack
前端:SpreadJS 16.1.1 后端: GcExcel 6.1.1 全能 SpreadJS 16.1.1此版本的产品中包含以下功能和增强功能。 添加了各种输入掩码样式选项。 添加了在保护工作表时设置密码以及在取消保护时验证密码的支持。 增强了组合图以将其显示为仪表图。 添加了…...
一个轻量的登录鉴权工具Sa-Token 集成SpringBoot简要步骤
Sa-Token 集成SpringBoot简要步骤 1.1 简单介绍 Sa-Token是一个轻量级Java权限认证框架。 主要解决的问题如下: 登录认证 权限认证 单点登录 OAuth2.0 分布式Session会话 微服务网关鉴权等一系列权限相关问题。 1.2 登录认证 设计思路 对于一些登录之后…...
day 44 完全背包:518. 零钱兑换 II;377. 组合总和 Ⅳ
完全背包:物品可以使用多次 完全背包1. 与01背包区别 518. 零钱兑换 II1. dp数组以及下标名义2. 递归公式3. dp数组如何初始化4. 遍历顺序:不能颠倒两个for循环顺序5. 代码 377. 组合总和 Ⅳ:与零钱兑换类似,但是是求组合数1. dp数组以及下标名义2. 递归…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...
ZYNQ学习记录FPGA(一)ZYNQ简介
一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...
快速排序算法改进:随机快排-荷兰国旗划分详解
随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...
