网络编程
其他图片来源未知,侵删。
OSI模型
发送方在一层一层的打包,接受方,一层一层解包,拿到数据。
我们要做的只是使用打包好的API函数,传递参数即可。
TCP/IP模型
可以理解为OSI七层模型的简化版本。
对比:
收发过程可以想象成收发快递。
每层只做它应该做的事,其余的它都不知道。
上层调用下层服务。
经典的分层模型。
双方遵守协议的内容,正确完成通信。
网络套接字编程
对比
TCP套接字
无论客户端还是服务端在发送的时候都多发送1个长度,字符串结束符。
TCP套接字服务端
#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);//htonl——
addrServer.sin_family = AF_INET;//协议栈
addrServer.sin_port = htons(6000);//端口-1024以下的端口是系统保留的,htons——大小端转换,x86小端,网络传输-大端
//绑定到本机
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套接字客户端
#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;
}
//创建TCP套接字
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();
// system("pause");
return 0;
}
UDP套接字
UDP套接字不需要监听、建立链接,绑上网卡和端口,直接发送就可以。
UDP套接字服务端
#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;
//绑定到本机6002端口
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套接字客户端
#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;
}
//创建UDP套接字
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;
}