网络编程
有些图片来源——https://blog.csdn.net/TT_love9527
其他图片来源未知,侵删。
OSI模型
![](/images/%E7%BD%91%E7%BB%9C.assets/image-20211113113551491.png)
发送方在一层一层的打包,接受方,一层一层解包,拿到数据。
![image-20211113114043879](/images/%E7%BD%91%E7%BB%9C.assets/image-20211113114043879.png)
我们要做的只是使用打包好的API函数,传递参数即可。
TCP/IP模型
可以理解为OSI七层模型的简化版本。
对比:
![image-20211113114251036](/images/%E7%BD%91%E7%BB%9C.assets/image-20211113114251036.png)
![image-20211113114406218](/images/%E7%BD%91%E7%BB%9C.assets/image-20211113114406218.png)
收发过程可以想象成收发快递。
![image-20211113114519988](/images/%E7%BD%91%E7%BB%9C.assets/image-20211113114519988.png)
每层只做它应该做的事,其余的它都不知道。
上层调用下层服务。
经典的分层模型。
双方遵守协议的内容,正确完成通信。
网络套接字编程
对比
![image-20211113114946319](/images/%E7%BD%91%E7%BB%9C.assets/image-20211113114946319.png)
TCP套接字
![image-20211113115130159](/images/%E7%BD%91%E7%BB%9C.assets/image-20211113115130159.png)
无论客户端还是服务端在发送的时候都多发送1个长度,字符串结束符。
TCP套接字服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| #include<WinSock2.h> #include <iostream> #pragma comment(lib,"ws2_32.lib")
int main(void) { WORD wVersion; WSADATA wsaData; int err; wVersion = MAKEWORD(1, 1); err = WSAStartup(wVersion, &wsaData); if (err) { return err; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return -1; } SOCKET sockServer = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addrServer; addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); addrServer.sin_family = AF_INET; addrServer.sin_port = htons(6000); bind(sockServer,(SOCKADDR*)&addrServer,sizeof(SOCKADDR)); std::cout << "Server start at port 6000" << std::endl; listen(sockServer,10); SOCKADDR_IN addrClient; int len = sizeof(SOCKADDR); char recvBuf[100]; char sendBuf[100]; while (1) { SOCKET sockConnect = accept(sockServer,(SOCKADDR*)&addrClient,&len); sprintf_s(sendBuf,100,"hello client"); send(sockConnect, sendBuf, strlen(sendBuf)+1,0); recv(sockConnect, recvBuf, 100, 0); std::cout << recvBuf << std::endl; closesocket(sockConnect); } closesocket(sockServer); WSACleanup(); return 0; }
|
TCP套接字客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include<iostream> #include<WinSock2.h> #pragma comment(lib,"ws2_32.lib")
int main(void) { WORD wVersion; WSADATA wsaData; int err; wVersion = MAKEWORD(1, 1); err = WSAStartup(wVersion, &wsaData); if (err) { return err; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return -1; } SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); addrSrv.sin_port = htons(6000); addrSrv.sin_family = AF_INET; connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); char sendBuf[] = "hello server"; char recvBuf[100]; send(sockClient, sendBuf, strlen(sendBuf)+1, 0); recv(sockClient, recvBuf, 100, 0); std::cout << recvBuf << std::endl; closesocket(sockClient); WSACleanup(); return 0; }
|
UDP套接字
![image-20211113203130824](/images/%E7%BD%91%E7%BB%9C.assets/image-20211113203130824.png)
UDP套接字不需要监听、建立链接,绑上网卡和端口,直接发送就可以。
UDP套接字服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| #include<iostream> #include<winsock2.h> #pragma comment(lib,"ws2_32.lib")
int main(void) { WORD wVersion; WSADATA wsaData; int err; wVersion = MAKEWORD(1, 1); err = WSAStartup(wVersion, &wsaData); if (err) { return err; } if (HIBYTE(wsaData.wVersion) != 1 || LOBYTE(wsaData.wVersion) != 1) { WSACleanup(); return -1; } SOCKET sockServer = socket(AF_INET,SOCK_DGRAM,0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); addrSrv.sin_port = htons(6002); addrSrv.sin_family = AF_INET; bind(sockServer,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); SOCKADDR_IN addrClient; int len = sizeof(SOCKADDR); char sendBuf[] = "hello client"; char recvBuf[100]; std::cout << "Start UDP Server at port 6002" << std::endl; while (1) { recvfrom(sockServer,recvBuf,100,0,(SOCKADDR*)&addrClient,&len); std::cout <<"Recv:"<< recvBuf << std::endl; sendto(sockServer, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrClient, len); std::cout << "Send:" << sendBuf << std::endl; }
return 0; }
|
UDP套接字客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #include<iostream> #include<winsock2.h> #pragma comment(lib,"ws2_32.lib")
int main(void) { WORD wVersion; WSADATA wsaData; int err; wVersion = MAKEWORD(1, 1); err = WSAStartup(wVersion, &wsaData); if (err) { return err; } if (HIBYTE(wsaData.wVersion) != 1 || LOBYTE(wsaData.wVersion) != 1) { WSACleanup(); return -1; } SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); addrSrv.sin_port = htons(6002); addrSrv.sin_family = AF_INET;
int len = sizeof(SOCKADDR); char sendBuf[] = "hello Server :)"; char recvBuf[100]; std::cout << "send to Server:" << sendBuf<<std::endl; sendto(sockClient, sendBuf, strlen(sendBuf) + 1,0,(SOCKADDR*)&addrSrv,len); recvfrom(sockClient, recvBuf, 100, 0,(SOCKADDR*)&addrSrv, &len); std::cout << "recv from Server:" << recvBuf << std::endl; closesocket(sockClient); WSACleanup(); return 0; }
|