团购网站开发的可行性分析,wordpress微信文章采集,网站开发与运营怎么样,郑州新动力网络技术是干嘛的网络编程技术
c/s简易模型–windows网络编程c#xff08;未使用select#xff09;
1.比如qq,DNF,LOL等这些我们下载客户端的#xff0c;都属于c/s模型的一个应用
2.c/s模型其实是概念层面的。实现层面可以是基于任何的网络协议
3.常见的还有b/s模型---浏览器/服务器模型 基…网络编程技术
c/s简易模型–windows网络编程c未使用select
1.比如qq,DNF,LOL等这些我们下载客户端的都属于c/s模型的一个应用
2.c/s模型其实是概念层面的。实现层面可以是基于任何的网络协议
3.常见的还有b/s模型---浏览器/服务器模型 基于http/https协议的要展示的效果
1局域网
2.广域网可通过内网穿透内网转发实现1sever服务器端分为以下7个步骤
打开网络库校验版本创建SOKCKET绑定地质与端口开始监听接受客户端链接创建客户端socket与客户端发送信息
1.0头文件
vs2019环境下 需注意scanf报错 解决方法 1添加宏定义#define _CRT_SECURE_NO_WARNINGS 2.改为scanf_s 代码
#define _CRT_SECURE_NO_WARNINGS
#includestdio.h
#include string.h
#include Ws2tcpip.h//调用inet_pton()函数替换inet_addr
#includeWinSock2.h
#pragma comment(lib,Ws2_32.lib)//库版本为2.21.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 shortwVersionRequired需要的网络库版本号此处用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_INET2IPV4AF_INET623IPV6AF_BTH32蓝牙地址协议AF_IRDA26红外数据歇会lrDA系列
参数2
参数取值含义–––SOCK_STREAM1提供带有OOB数据传输机制的顺序可靠双向基于链接的字节流。此套接字类型使用传输控制协议TCP作为internet地址系列AF_INET或AF_INET6SOCK_DGRAM2一种支持数据报的套接字类型固定通常很小最大长度的无连接不可靠的缓冲区使用用户数据报协议UDP作为internet地址系列AF_INET或AF_INET6SOCK_RAW3要操作IPV4表头需在套接字上设IP_HDRINCL套接字选型要操作IPV6表头需在套接字上设IPV6_HDRINCL套接字选型SOCK_RDM4提供可靠消息数据报仅在安装了可靠多播协议时才支持此类型值SOCK_SEQPACKET5提供基于数据报的伪流数据包
参数3
参数数值对应协议af参数类型参数IPPROTO_TCP6TCPSOCK_STREAMAF_INET或AF_INET6IPPROTO_UDP17UDPSOCK_DGRAMAF_INET或AF_INET6IPPROTO_ICMP1ICMPSOCK RAW或未指定AF_UNSPEC,AF_INET或AF_INET6IPPROTO_IGMP2IGMPSOCK RAW或未指定AF_UNSPEC,AF_INET或AF_INET6IPPROTO_RM113PGMSOCK_RDMAF_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 bresbind(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顺序不可颠倒 未写完过两天写