网络编程技术-----windows网络编程
网络编程技术
c/s简易模型–windows网络编程c++(未使用select)
1.比如qq,DNF,LOL等这些我们下载客户端的,都属于c/s模型的一个应用
2.c/s模型其实是概念层面的。实现层面可以是基于任何的网络协议
3.常见的还有b/s模型---浏览器/服务器模型 基于http/https协议的要展示的效果:
1:局域网
2.广域网可通过内网穿透,内网转发实现
1:sever服务器端分为以下7个步骤
- 打开网络库
- 校验版本
- 创建SOKCKET
- 绑定地质与端口
- 开始监听
- 接受客户端链接(创建客户端socket)
- 与客户端发送信息
1.0头文件
vs2019环境下 需注意scanf报错
解决方法:
1:添加宏定义#define _CRT_SECURE_NO_WARNINGS
2.改为scanf_s
代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include <string.h>
#include <Ws2tcpip.h>//调用inet_pton()函数替换inet_addr
#include<WinSock2.h>
#pragma comment(lib,"Ws2_32.lib")//库版本为2.2
1.1打开网络库----WSASstartup()
WSAStartup
目前网络库版本:
1.1.0
2.1.1
3.2.0
4.2.1
5.2.2
不管是64编译环境还是32编译环境都用这个,不管是第一版的winsock.h,还是第二版的winsock2.h,都用ws2_32.lib
int WSAStartup(
WORD wVersionRequired,
[out] LPWSADATA lpWSAData
);
WSAS四个字符:
w windows
s socket
a Asynchronous 异步
s startup 启动
类型 | 参数 | 作用 |
---|---|---|
WORD 转定义unsigned short | wVersionRequired | 需要的网络库版本号此处用2.2版本 |
[out] lpWSAData | 指向WSADATA数据结构的指针 ,用于接收 Windows 套接字实现的详细信息。 |
参数2:
1.注意:当看到参数有LP P前缀是,传对应类型变量地址,这是win32API规范
typedef struct WSAData {
WORD wVersion;//我们要使用的版本
WORD wHighVersion;//系统能提供给我们最高的版本
unsigned short iMaxSockets;//返回可用socket的数量,2版本之后就没用了
unsigned short iMaxUdpDg;//UDP数据包信息的大小,2版本之后就没用了
char *lpVendorInfo;//供应商特定的信息,2版本之后就没用了
char szDescription[WSADESCRIPTION_LEN + 1];
char szSystemStatus[WSASYS_STATUS_LEN + 1];
//上两行:当前库的描述信息,,2版本之后就没用了
} WSADATA;
当输入版本不存在时:得到当前输入板本最大版本(主版本0除外)
返回值 | 作用 | 解决方法 |
---|---|---|
0 | 执行正确 | ---- |
WSASYSNOTREADY 10091 | 底层网络子系统尚未准备好进行网络通信 | 系统配置问题,重启,检查ws2_32库是否存在或者是否在环境配置目录下 |
WSAVERNOTSUPPORTED 10092 | 此特定 Windows 套接字实现不提供请求的 Windows 套接字支持版本。 | 使用版本不支持,更新网络库 |
WSAEINPROGRESS 10036 | 操作当前函数运行期间,由于某些原因造成阻塞,会返回在这个错误码,其他操作均禁止 | 重启 |
WSAEPROCLIM 10067 | 已达到 Windows 套接字实现支持的任务数量限制。 | 网络连接达到上限或阻塞,关闭不必要的软件 |
WSAEFAULT 10014 | 该lpWSAData参数不是一个有效的指针 | 程序有误请检查,参数写错 |
代码
//打开网络库//int WSAStartup(WORD wVersionRequired, LPWSADATA lpWASAData);WSADATA wdScokMsg;WORD wdVersion = MAKEWORD(2, 2);//用宏存版本 int nRes = WSAStartup(wdVersion, &wdScokMsg);if (nRes != 0){switch (nRes){case WSASYSNOTREADY://底层网络子系统尚未准备好进行网络通信,重启检查ws2_32库是否存在或者是否在环境配置目录下printf("系统配置问题,重启");break;case WSAVERNOTSUPPORTED:printf("解决方案:使用版本不支持,更新网络库");break;case WSAEINPROGRESS:printf("解决方案:重启");//当前函数运行期间,由于某些原因造成阻塞,会返回在这个错误码,其他操作均禁止break;case WSAEPROCLIM:printf("解决方案:网络连接达到上限或阻塞,关闭不必要的软件");break;case WSAEFAULT:printf("解决方案:程序有误请检查,参数写错");break;}return 0;}
1.2校验版本
#define MAKEWORD(a, b) ((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8))
高八位表示副版本号,低八位表示主版本号 (HIBYTE高字节副版本 LOBYTE低字节主版本)
代码
if (2 != HIBYTE(wdScokMsg.wVersion) || 2 != LOBYTE(wdScokMsg.wVersion))//版本不成功时{printf("版本有问题");WSACleanup();//关闭网络库return 0;}
出错需关闭库并结束函数
注意:WSAStartup()与WSACleanup()是成对出现
1.2. 创建SOKCKET
SOCKET WSAAPI socket(
[in] int af,
[in] int type,
[in] int protocol
);
SOCKET:
socket将底层复杂的协议体系,执行流程,进行封装,就是一个socket–是我们调用协议进行通信的操作接口,每个客户端,服务器都有一个SOCKET,通信时给谁通信就传递谁的SOCKET
本质:
是一个整数数据类型,但是是唯一的,标识我当前的应用程序,协议特点等信息
参数 | 类型 |
---|---|
int af | 地址 |
int type | 套接字 |
int protocol | 协议 |
参数1:
参数 | 取值 | 含义 |
---|---|---|
AF_INET | 2 | IPV4 |
AF_INET6 | 23 | IPV6 |
AF_BTH | 32 | 蓝牙地址协议 |
AF_IRDA | 26 | 红外数据歇会(lrDA)系列 |
参数2:
参数 | 取值 | 含义 |
---|---|---|
– | – | – |
SOCK_STREAM | 1 | 提供带有OOB数据传输机制的顺序,可靠,双向,基于链接的字节流。此套接字类型使用传输控制协议TCP作为internet地址系列(AF_INET或AF_INET6) |
SOCK_DGRAM | 2 | 一种支持数据报的套接字类型,固定(通常很小)最大长度的无连接,不可靠的缓冲区,使用用户数据报协议(UDP)作为internet地址系列(AF_INET或AF_INET6) |
SOCK_RAW | 3 | 要操作IPV4表头,需在套接字上设IP_HDRINCL套接字选型,要操作IPV6表头,需在套接字上设IPV6_HDRINCL套接字选型, |
SOCK_RDM | 4 | 提供可靠消息数据报,仅在安装了可靠多播协议时才支持此类型值 |
SOCK_SEQPACKET | 5 | 提供基于数据报的伪流数据包 |
参数3
参数 | 数值 | 对应协议 | af参数 | 类型参数 |
---|---|---|---|---|
IPPROTO_TCP | 6 | TCP | SOCK_STREAM | AF_INET或AF_INET6 |
IPPROTO_UDP | 17 | UDP | SOCK_DGRAM | AF_INET或AF_INET6 |
IPPROTO_ICMP | 1 | ICMP | SOCK RAW或未指定 | AF_UNSPEC,AF_INET或AF_INET6 |
IPPROTO_IGMP | 2 | IGMP | SOCK RAW或未指定 | AF_UNSPEC,AF_INET或AF_INET6 |
IPPROTO_RM | 113 | PGM | SOCK_RDM | AF_INET(仅在安装了可靠多播协议时才支持此协议值) |
注意:
- 参数1,2,3三者配套
- 要使用设备支持的协议
- 参数3中可填0,系统会自动帮我们选择协议类型,尽量避免这样写,以免以后的代码升级出BUG。
返回值
如果没有发生错误, 套接字返回句柄。否则,返回一个 INVALID_SOCKET 值,并且可以通过调用WSAGetLastError来检索特定的错误代码 。(使用完毕用CloseSocket(###)关闭句柄)
代码
SOCKET socketServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (INVALID_SOCKET == socketServer)//无效socket失败时关闭网络库情况{int a = WSAGetLastError();WSACleanup();return 0;}
1.3.绑定地质与端口----bind()
作用
为socket绑定端口号与具体地址
//ipconfig查看ip地址
//netstat -ano查看被使用所有端口
//netstat -ano|findstr "12345"检查端口是否被占用cmd中
端口0-65535 而0-1023一般为系统保留占用端口
int bind(
[in] SOCKET s,
const sockaddr *addr,
[in] int namelen
);
参数1
绑定实质的地址和端口号
参数2
结构体
- 地址类型
- 装ip地址
- 端口号
struct sockaddr {
ushort sa_family;//2字节
char sa_data[14];//14字节
};
struct sockaddr_in {
short sin_family;//2字节
u_short sin_port;//2字节
struct in_addr sin_addr;//4字节
char sin_zero[8];//8字节
};
示例:
struct sockaddr_in si;si.sin_family = AF_INET;si.sin_port = htons(12345);//htons宏将整形转换为端口号的无符号整形inet_pton(AF_INET, "127.0.0.1", &si.sin_addr.S_un.S_addr);调用inet_aton函数替换inet_addr(不支持旧函数)转换为无符号long
可以把下面的强转为上面的类型
参数3
参数2的类型大小–sizeof(参数2)
返回值
成功返回0
失败返回SOCKET_ERROR(调用WSAGetLastError()获得错误码)
可在vs2019中输入错误码查询错误原因
代码
struct sockaddr_in si;si.sin_family = AF_INET;si.sin_port = htons(12345);//htons宏将整形转换为端口号的无符号整形inet_pton(AF_INET, "127.0.0.1", &si.sin_addr.S_un.S_addr);//调用inet_aton函数替换inet_addr(不支持旧函数)转换为无符号long//int bres=bind(socketServer, (const struct sockaddr*)&si, sizeof(si));检查bind返回值if (SOCKET_ERROR == bind(socketServer, (const struct sockaddr*)&si, sizeof(si))){int a = WSAGetLastError();//取错误码printf("服务器bind失败错误码为:%d\n", a);closesocket(socketServer);//释放WSACleanup();//关闭网络库return 0;}printf("服务器端bind成功\n");
1.4. 开始监听 ----listen()
将套接字置于正在侦听传入链接的状态
int WSAAPI listen(
[in] SOCKET s,
[in] int backlog
);
WSAAPI:调用约定
这个可以忽略,给系统看的,和我们无关
决定三个;
- 函数名字的编译方式
- 参数的入栈顺序
- 函数的调用时间
参数1
服务器socket
参数2
1.意义:挂起连接队列的最大长度(系统创建队列记录暂时不能处理的请求)可手动设置2~20+,
2.一般填写SOMAXCONN----让系统自动选择最合适的个数(不同系统环境不一样)
返回值
成功返回0
失败返回SOCKET_ERROR 具体错误码WSAGetLastError()
释放
代码
if (SOCKET_ERROR == listen(socketServer, SOMAXCONN))//(服务器句柄,SOMAXCONN系统自动选择最合适的挂起连接队列的最大长度也可手动设置一般为2-20+){int a = WSAGetLastError();//取错误码printf("服务器监听失败错误码为:%d\n", a);closesocket(socketServer);//释放WSACleanup();//关闭网络库return 0;}printf("服务器端监听成功!\n");
1.5. 接受客户端链接(创建客户端socket)----accept()
作用:
- 允许在套接字上进行传入连接尝试
- 将客户端信息绑定到一个新创建socket,通过返回值返回给客户端
- 一次只能创建一个,多个需调用多次
SOCKET WSAAPI accept(
[in] SOCKET s,
[out] sockaddr *addr,
[in, out] int *addrlen
);
参数1
上面创建的socket 先处于监听状态然后来的连接都有这个管理,我们通过这个句柄取客户端信息
参数2
客户端地址端口信息结构体–传址调用
意义:系统帮我们监视着客户端的动态,记录客户端的信息
参数3
参数2的大小
参数2,3可设置为NULL,即不直接得到客户端的地址,端口号,
可通过
getpeername()通过函数得到客户端信息
getsockname(Socket,(sockaddr*)&addr,&len)//得到本地服务器
返回值
成功返回给客户端包好的socket(于客户端通信就靠这个)
失败返回INVALID_SOCKET(获取错误码)
释放
缺点
- 阻塞,同步
- 多个链接需用循环
代码
struct sockaddr_in clientMsg;int len = sizeof(clientMsg);//accept//一次只能创建一个客户端socket,有几个客户端链接就要调用几次SOCKET socketClient = accept(socketServer, (struct sockaddr*)&clientMsg, &len);//后两个参数也可设置为NULL表示不直接得到客户端的地址,端口号if (INVALID_SOCKET == socketClient){int a = WSAGetLastError();//取错误码printf("获取客户端句柄失败错误码为:%d\n", a);closesocket(socketServer);//释放WSACleanup();//关闭网络库return 0;}printf("客户端连接成功!\n");
1.6. 与客户端发送信息
作用:得到指定客户端(参数1)发来的消息
原理:
本质是复制----数据的接收都是由协议本身做的,也就是socket的底层做的,系统会有一段缓冲区,存储接收的数据,调用recv()就是通过socket找到缓冲区并将数据复制
int WSAAPI recv(
[in] SOCKET s,
[out] char *buf,
[in] int len,
[in] int flags
);
参数1
客户端的socket
参数2
客户端消息的存储空间即字节串,一般1500字节(网络传输的最大单元),协议规定客户端发过来最大1500字节,多种情况最优值
参数3
想要读取的字节个数,一般-1,把\0字符串结尾留出来
参数4
数据的读取方式
0----依次读出 读出来就删 可计数多少字节
MSG_PEEK----读了不删 读数据不行 无法计数
MSG_OOB----传输一段距离在外带一个额外特殊数据 REF 793与RFC 1122协议不兼容 可用两次send与recv代替
MSG_WAITALL----当buf字节==参数3才读取
返回值
读出来字节数大小
- 读没了 在recv函数卡住等待客户端发来数据即阻塞,同步
- 客户端下线,端返回0 释放客户端socket
- 执行失败返回SOCKTET_ERROR
注意:closesocket()与WSACLeanup()顺序不可颠倒
未写完过两天写
网络编程技术-----windows网络编程相关推荐
- 网络存储技术Windows server 2012(项目三 存储池的配置与管理)
网络存储技术Windows server 2012(项目三 存储池的配置与管理) 目录 前言 一.项目背景 二.项目实训题 任务实操步骤 1.添加3块硬盘到存储服务器中,创建1个存储池. 2.在存储池 ...
- 网络存储技术Windows server 2012 (项目二十二 远程异地灾备中心的部署)
网络云存储技术Windows server 2012 (项目二十二 远程异地灾备中心的部署) 前言 网络存储技术,是以互联网为载体实现数据的传输与存储,它采用面向网络的存储体系结构,使数据处理和数据存 ...
- 网络存储技术Windows server 2012 (项目一 基本磁盘的配置与管理)
网络存储技术Windows server 2012 (项目一 基本磁盘的配置与管理) 前言 网络存储技术,是以互联网为载体实现数据的传输与存储,它采用面向网络的存储体系结构,使数据处理和数据存储分离. ...
- 网络存储技术Windows server 2012 (项目八 文件共享与磁盘映射)
网络存储技术Windows server 2012 (项目八 文件共享与磁盘映射) 目录 前言 一.项目背景 二.项目实训题 三.操作步骤 1.在文件服务器上创建用户tom和jack: 2.在文件服务 ...
- 网络存储技术Windows server 2012 (项目二 动态磁盘的配置与管理)
网络存储技术Windows server 2012 (项目二 基本磁盘的配置与管理) 目录 前言 一.项目背景 二.项目实训题 1.项目1 2.项目2 3.项目3 前言 网络存储技术,是以互联网为载体 ...
- 网络存储技术Windows server 2012 (项目五 存储服务器的数据快照计划与故障还原)
网络存储技术Windows server 2012 (项目五 存储服务器的数据快照计划与故障还原) 目录 前言 一.项目背景 二.项目实训题 三.环境部署 1.在[新加卷E]新建一个共享目录 2.将共 ...
- 网络存储技术Windows server 2012 (项目四 存储池的高级配置与管理)
网络存储技术Windows server 2012(项目四 存储池的高级配置与管理) 目录 前言 一.项目背景 一.项目实训题 二.环境准备 三.操作步骤 1.分别用3个物理硬盘创建两个存储池,存储池 ...
- 网络存储技术Windows Server 2012(汇总目录)
网络存储技术Windows Server 2012-- 文章视频讲解汇总目录 前言 网络存储技术,是以互联网为载体实现数据的传输与存储,它采用面向网络的存储体系结构,使数据处理和数据存储分离.它通过网 ...
- java web 编程技术 pdf_Java WEB编程技术.pdf
您所在位置:网站首页 > 海量文档  > 计算机 > Java Java WEB编程技术.pdf289页 本文档一共被 ...
- 2018-2019-2 20165205 网络对抗技术 Exp7 网络欺诈防范
2018-2019-2 20165205 网络对抗技术 Exp7 网络欺诈防范 2018-2019-2 20165205 网络对抗技术 Exp7 网络欺诈防范 实验内容 本次实践的目标理解常用网络欺诈 ...
最新文章
- ssh 看apache_使用Apache KeyedObjectPool的ssh连接池
- leetcode226. 翻转二叉树(dfs)
- Linux——Ubuntu安装Fcitx以及Fcitx输入中文不显示候选词框的解决办法
- 归并排序与快速排序比较
- Docker方式安装SonarQube
- 全网首发:WINDOWS某些文件夹,提供管理员权限后也无法删除,正确解决办法
- [C/C++] C++中new的语法规则
- 语义分割数据集——VOC2012
- android系统的官网下载地址,Android安卓10.0系统官方正式版
- 2022年信息系统监理师考试大纲
- ACL 2017 录用论文整理(长文)
- 云服务器无法连接怎么办
- Windows环境下用C语言实现CS模型(基于TCP协议)
- w ndows无法连接到无线网络,windows无法连接到无线网络,详细教您windows无法连接到无线网络怎么办...
- 算法题--递归解法(化整思想、24点、全排列、单词迷宫解法加步骤)
- FCoin“出事”后,团队关键人物回复了!
- 强大的 Python 信号库:blinker 入门教程
- android 蒙层动画,Android酷炫加载进度动画
- 解决wps VBA安装的问题
- 鸿蒙系统与nblot,华为鸿蒙操作系统,和想象中的不一样