当前位置: 首页 > news >正文

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网络编程的学习&#xff0c;在学习的时候总是陷入Windows复杂的参数&#xff0c;纠结于这些。从老师的讲解中&#xff0c;这些内容属于是定式&#xff0c;主要学习写的逻辑。给自己提个醒&#xff0c;要把精力放在正确的位置&#xff0c;不要无端耗费精力。…...

leetcode1985. 找出数组中的第 K 大整数

给你一个字符串数组 nums 和一个整数 k 。nums 中的每个字符串都表示一个不含前导零的整数。 返回 nums 中表示第 k 大整数的字符串。 注意&#xff1a;重复的数字在统计时会视为不同元素考虑。例如&#xff0c;如果 nums 是 ["1","2","2"]&am…...

基于深度学习的高精度野生动物检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度野生动物检测&#xff08;水牛、犀牛、斑马和大象&#xff09;识别系统可用于日常生活中或野外来检测与定位野生动物目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的野生动物目标检测识别&#xff0c;另外支持结果可视…...

从零开始 Spring Boot 35:Lombok

从零开始 Spring Boot 35&#xff1a;Lombok 图源&#xff1a;简书 (jianshu.com) Lombok是一个java项目&#xff0c;旨在帮助开发者减少一些“模板代码”。其具体方式是在Java代码生成字节码&#xff08;class文件&#xff09;时&#xff0c;根据你添加的相关Lombok注解或类来…...

深入解析Spring源码系列:Day 6 - Spring MVC原理

深入解析Spring源码系列&#xff1a;Day 6 - Spring MVC原理 欢迎来到本系列的第六篇博客。在前几篇博客中&#xff0c;我们探索了Spring框架的核心概念&#xff0c;包括Bean的生命周期、作用域、AOP原理和事务管理。今天&#xff0c;我们将深入研究Spring框架中的MVC&#xf…...

Cmake中message函数 如何优雅地输出

message函数说明 在CMake中&#xff0c;message()函数用于向终端输出信息。 message([<mode>] "message text" ...)函数的<mode>参数可以是以下之一&#xff1a; (none): 等同于STATUS&#xff0c;但不推荐使用。STATUS: 输出的信息会被发送到CMake的…...

人工智能基础部分20-生成对抗网络(GAN)的实现应用

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能基础部分20-生成对抗网络(GAN)的实现应用。生成对抗网络是一种由深度学习模型构成的神经网络系统&#xff0c;由一个生成器和一个判别器相互博弈来提升模型的能力。本文将从以下几个方面进行阐述&#xff1…...

JavaScript表单事件(上篇)

目录 一、input: 当表单元素的值发生改变时触发&#xff0c;适用于大多数表单元素。 二、change: 当表单元素的值发生改变且失去焦点时触发&#xff0c;适用于输入框、下拉列表等。 三、submit: 当表单提交时触发&#xff0c;适用于 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执行结果&#xff0c;用时 54 毫秒 其中JSON转字符13.5209毫秒 jSON数据长度: 增…...

编码,Part 1:ASCII、汉字及 Unicode 标准

个人博客 编码的历史由来就懒得介绍了&#xff0c;只需要知道人类处理文本信息是以字符为基本单位&#xff0c;而计算机在最底层只认识 0/1&#xff0c;所以当计算机要为人类存储/呈现字符时&#xff0c;就需要有一个规则&#xff0c;在字符和 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是磁盘启动的引导程序&#xff0c;其概括起来就是代码的搬运工&#xff0c;将代码搬到合适的位置。下图是对搬运过程的概括&#xff0c;可以有个印象&#xff0c;后面将详细讲解。 bootsect.s主要做了如下的三件事: 搬…...

django组件552

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…...

【枚举算法的Java实现及其应用】

文章目录 枚举算法概述枚举算法的实现步骤Java实现枚举算法枚举算法的底层工作原理枚举算法的底层代码讲解枚举算法的实际应用场景枚举算法在场景中解决的问题总结 枚举算法概述 枚举算法是一种通过列举所有可能情况来解决问题的方法。这种算法在解决一些特定类型的问题时非常…...

linux led 驱动

前言 今天是儿童节&#xff0c;挣个奖牌给小孩玩玩。 在 linux 驱动大家庭中&#xff0c;LED 驱动算是个儿童&#xff0c;今天就写写他吧。正好之前写过他的婴儿时期《i.MX6ULL 裸机点亮 LED》&#xff0c;记得那时候他还穿着开裆裤呢&#xff0c;裸鸡嘛。 ioremap() 裸机程…...

平面最近点对(分治算法)

文章目录 平面最近点对&#xff08;分治算法&#xff09;Solution流程完整模板代码 平面最近点对&#xff08;分治算法&#xff09; 文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 平面最近点对&#xff08;加强版&#xff09; - 洛谷 给你一些点&#xff0c;求两点之…...

【基于前后端分离的博客系统】Servlet版本

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一. 项目简介 1. 项目背景 2. 项目用到的技…...

在线Excel绝配:SpreadJS 16.1.1+GcExcel 6.1.1 Crack

前端&#xff1a;SpreadJS 16.1.1 后端&#xff1a; GcExcel 6.1.1 全能 SpreadJS 16.1.1此版本的产品中包含以下功能和增强功能。 添加了各种输入掩码样式选项。 添加了在保护工作表时设置密码以及在取消保护时验证密码的支持。 增强了组合图以将其显示为仪表图。 添加了…...

一个轻量的登录鉴权工具Sa-Token 集成SpringBoot简要步骤

Sa-Token 集成SpringBoot简要步骤 1.1 简单介绍 Sa-Token是一个轻量级Java权限认证框架。 主要解决的问题如下&#xff1a; 登录认证 权限认证 单点登录 OAuth2.0 分布式Session会话 微服务网关鉴权等一系列权限相关问题。 1.2 登录认证 设计思路 对于一些登录之后…...

day 44 完全背包:518. 零钱兑换 II;377. 组合总和 Ⅳ

完全背包&#xff1a;物品可以使用多次 完全背包1. 与01背包区别 518. 零钱兑换 II1. dp数组以及下标名义2. 递归公式3. dp数组如何初始化4. 遍历顺序:不能颠倒两个for循环顺序5. 代码 377. 组合总和 Ⅳ:与零钱兑换类似&#xff0c;但是是求组合数1. dp数组以及下标名义2. 递归…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

android13 app的触摸问题定位分析流程

一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...