服务端保持监听客户端, 服务端采用select实现,可以监听多个客户端
客户端源码
在这里插入代码片
```#include <iostream>
//#include
#include
#include
using namespace std;
#pragma comment(lib, "Ws2_32.lib")
int main() {
WSADATA wd;
int result;
result = WSAStartup(MAKEWORD(2, 2), &wd);
if (result != 0) {
cout << "WSAStartup error" << endl;
return 0;
}
//创建套接字
SOCKET c_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (c_socket == INVALID_SOCKET) {
cout << "socket error" << endl;
return 0;
}
sockaddr_in c_addr;
inet_pton(AF_INET, "127.0.0.1", &c_addr.sin_addr.S_un.S_addr);
c_addr.sin_family = AF_INET;
c_addr.sin_port = htons(8888);
int len = sizeof(c_addr);
result = connect(c_socket, (sockaddr*)&c_addr, len);
if (result == INVALID_SOCKET) {
cout << "connect error" << endl;
return 0;
}
char sendbuf[1024] = { 0 };
cout << "client输入数据:";
cin >> sendbuf;
//send
result = send(c_socket, sendbuf, sizeof(sendbuf), 0);
if (result == SOCKET_ERROR) {
cout << "client send error" << endl;
return 0;
}
//recv
char recvbuf[1024] = { 0 };
result = recv(c_socket, recvbuf, sizeof(recvbuf), 0);
if (result == 0) {
cout << "recv error" << endl;
return 0;
}
cout << "servic发送的数据:" << recvbuf << endl;
//close
closesocket(c_socket);
WSACleanup();
return 0;
}
服务端源码
#include
//#include
#include
#include
//#include
//#include
using namespace std;
//导入动态库
#pragma comment(lib,"ws2_32.lib")
int __cdecl main(int argc, char** argv) {
WSADATA wd; //创建wd的WSADATA对象
SOCKET s_socket = INVALID_SOCKET;
int result;
//初始化winsock
//调用WSAStartup
result = WSAStartup(MAKEWORD(2, 2), &wd);
if (result != 0) {
//printf("WSAStartup 失败:d%\n", result);
}
//1 创建套接字
SOCKET ser_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//判断套接字是否有效
if (ser_socket == INVALID_SOCKET) {
cout << "套接字不可用";
return 0;
}
//2 绑定端口和地址 sockaddr_in 是一个结构体
sockaddr_in addr;
/* addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); 使用这个会报错*/
inet_pton(AF_INET,"127.0.0.1",&addr.sin_addr.S_un.S_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(8888);
int len = sizeof(addr);
result = bind(ser_socket, (LPSOCKADDR)&addr, len);
if (result == SOCKET_ERROR) {
cout << "socket error"<< result << endl;
return 0;
}
cout << "服务器启动成功,正在等待客户端连接" << endl;
//3 监听
if (listen(ser_socket, 5) == SOCKET_ERROR) {
cout << "listen error" << endl;
}
FD_SET read_set;//创建文件描述集合
FD_ZERO(&read_set);//清空文件描述集合
FD_SET(ser_socket, &read_set);//将监听套接字放入文件描述集合
timeval timeout{ 0,0 };//select超时设置
while (true) {
FD_SET temp_set;
FD_ZERO(&temp_set);
temp_set = read_set;
int select_num = select(0, &temp_set, NULL, NULL, &timeout);
if (select_num == SOCKET_ERROR) {
continue;
}
for (int i = 0; i < temp_set.fd_count; i++) {
SOCKET s_df = temp_set.fd_array[i];
if (s_df == ser_socket) { // 判断监听套接字是否就绪
//4 接收连接
//获取客户端IP地址和端口
sockaddr_in client_addr;
client_addr.sin_family = AF_INET;
int client_len = sizeof(client_addr);
s_socket = accept(ser_socket, (sockaddr*)&client_addr, &client_len);
if (s_socket == INVALID_SOCKET) {
cout << "accept error" << endl;
continue;
}
else {
cout << "客户端连接成功" << endl;
}
char ipbuff[100];
string remote_host = inet_ntop(AF_INET, &addr.sin_addr.S_un.S_addr, ipbuff, 20);
cout << "接收到客户机:" << remote_host << " 端口号:" << addr.sin_port << endl;
// 5接收和发送
char recvbuf[1024] = { 0 };
result = recv(s_socket, recvbuf, sizeof(recvbuf), 0);
if (result == 0 || result == SOCKET_ERROR) {
closesocket(s_df);
FD_CLR(s_df, &read_set);//从集中清除套接字
cout << "结束连接" << result << endl;
}
cout << "client发送的数据:" << recvbuf << endl;
cout << "service输入数据:";
char sendbuf[1024] = { 0 };
cin >> sendbuf;
result = send(s_socket, sendbuf, sizeof(sendbuf), 0);
if (result == SOCKET_ERROR) {
cout << "service send error" << endl;
}
if (s_socket == INVALID_SOCKET) {
cout << "socket error" << endl;
return 0;
}
}
else {
}
}
}
while (s_socket) {
}
// 6关闭
closesocket(s_socket);
WSACleanup();
system("pause");
return 0;
}