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. 递归…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
MySQL 主从同步异常处理
阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示ÿ…...

Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...