CS模型
Client/Server模型,客户端和服务端模型,服务端程序在服务器上一直开放,等待客户端程序接入。客户端程序在用户电脑上执行,打开后主动给服务端发送请求,然后建立连接,相互通信,直到服务端或客户端取消连接。
套接字
socket:英文原意是插座。它是TCP协议的端口,由于TCP提供的是点对点通信,因此每条TCP连接都由一组套接字确定。socket介于应用层和传输层之间,通过IP实现主机间的交流,通过port实现应用之间的交流。
定义
$$
socket = (IP:port)
$$
$$
TCP连接 ::={socket_1,socket_2}
$$
其中的两个socket分别为客户端和服务端的ip与端口号。
分类
- 流式套接字:用于TCP
- 数据包套接字:用于UDP
- 原始套接字:用于自定义底层协议
CPP实现方法
Windows中,使用
来使用套接字
CS具体内容
服务端和客户端分别建立套接字,设定对应ip和port
服务端等待连接,客户端请求连接
连接成功后,相互发送消息到缓冲区
结束后关闭。
CPP实现
socket函数,创建socket并设定模式,这里使用TCP
bind函数,绑定socket到ip:port上
listen函数,服务器监听对应端口有无信息
accept函数无限等待连接,获取客户端套接字,返回后表示连接成功,connect函数请求连接
recv函数接收数据,send函数发送数据
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
| #include<iostream> #include<WinSock2.h> #include<WS2tcpip.h> #pragma comment(lib,"ws2_32.lib")
int main(int argc, char* argv[]) {
WSADATA data; if (WSAStartup(MAKEWORD(2, 2), &data)) { std::cerr << "WSAdata初始化失败" << std::endl; }
SOCKET cSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (cSocket == INVALID_SOCKET) { std::cerr << "套接字创建失败" << std::endl; WSACleanup(); return 1; }
sockaddr_in saddr; saddr.sin_family = AF_INET; InetPton(AF_INET, L"127.0.0.1", &saddr.sin_addr);
saddr.sin_port = htons(4567);
if (connect(cSocket, (SOCKADDR*)&saddr, sizeof(saddr)) == SOCKET_ERROR) { std::cerr << "连接到服务器失败" << std::endl; closesocket(cSocket); WSACleanup(); return 1;
} const char* sendData = "Hello,world"; if (send(cSocket, sendData, strlen(sendData), 0) == SOCKET_ERROR) { std::cerr << "发送数据失败" << std::endl; closesocket(cSocket); WSACleanup(); return 1; }
closesocket(cSocket); WSACleanup(); return 0; }
|
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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| #include<iostream> #include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
int main(int argc, char* argv[]) {
WSADATA data; if (WSAStartup(MAKEWORD(2, 2), &data)) { std::cerr << "WSAdata初始化失败" << std::endl; }
SOCKET sSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sSocket == INVALID_SOCKET) { std::cerr << "套接字创建失败" << std::endl; WSACleanup(); return 1; }
sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = INADDR_ANY; saddr.sin_port = htons(4567);
if (bind(sSocket, (SOCKADDR*)&saddr, sizeof(saddr)) == SOCKET_ERROR) { std::cerr << "绑定失败" << std::endl; closesocket(sSocket); WSACleanup(); return 1;
} if (listen(sSocket, SOMAXCONN) == SOCKET_ERROR) { std::cerr << "监听失败" << std::endl; closesocket(sSocket); WSACleanup(); return 1; }
SOCKET cSocket; sockaddr_in caddr; int addrSize = sizeof(caddr); cSocket = accept(sSocket, (SOCKADDR*)&caddr, &addrSize); if (cSocket == INVALID_SOCKET) { std::cerr << "接受连接失败" << std::endl; closesocket(sSocket); WSACleanup(); return 1; }
char recvbuf[512]; int bytesReceived; while ((bytesReceived = recv(cSocket, recvbuf, sizeof(recvbuf) - 1, 0)) > 0) { recvbuf[bytesReceived] = '\0'; std::cout << recvbuf << std::endl;
} if (bytesReceived == SOCKET_ERROR) { std::cerr << "接收数据失败" << std::endl; } closesocket(cSocket); closesocket(sSocket); WSACleanup(); return 0; }
|