简单的小程序,vs2015编译通过
server
#include <tchar.h> #include <winsock2.h> #include <stdio.h> #include <windows.h> #pragma comment(lib,"ws2_32.lib") #define PORT 2000 //端口号 typedef struct /* message structure */ { UINT16 type; char data[1024]; } msg_t; #define MSG_TYPE1 1 /* application specific msg */ #define MSG_TYPE2 2 /* another one */ #define MSG_HEARTBEAT 3 /* heartbeat message */ #define T1 60 /* idle time before heartbeat */ #define T2 10 /* time to wait for response */ int _tmain(int argc, _TCHAR* argv[]) { WSADATA wsa; //初始化套接字DLL if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("套接字初始化失败!"); exit(-1); } SOCKET serverSocket; if ((serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { printf("创建套接字失败!"); exit(-1); } struct sockaddr_in serverAddress; memset(&serverAddress, 0, sizeof(sockaddr_in)); serverAddress.sin_family = AF_INET; serverAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY); serverAddress.sin_port = htons(PORT); if (bind(serverSocket, (sockaddr*)&serverAddress, sizeof(serverAddress)) == SOCKET_ERROR) { printf("套接字绑定到端口失败!端口: %d ", PORT); return -1; } //进入侦听状态 if (listen(serverSocket, SOMAXCONN) == SOCKET_ERROR) { printf("侦听失败!"); return -1; } printf("服务器端口: %d 正在监听...... ", PORT); //非阻塞 ULONG nonblock = 1; if (ioctlsocket(serverSocket, FIONBIO, &nonblock) == SOCKET_ERROR) { printf("ioctlsocket() failed with error %d ", WSAGetLastError()); return -1; } SOCKET acceptSocket;//用来和客户端通信的套接字 struct sockaddr_in clientAddress;//用来和客户端通信的套接字地址 memset(&clientAddress, 0, sizeof(clientAddress)); int addrlen = sizeof(clientAddress); //fd_set fdRead; fd_set fdSocket; FD_ZERO(&fdSocket); FD_SET(serverSocket, &fdSocket); struct timeval tv; tv.tv_sec = T1 + T2; tv.tv_usec = 0; int missed_heartbeats = 0; msg_t msg; while (true) { fd_set fdRead = fdSocket; int nRet = select(serverSocket + 1, &fdRead, NULL, NULL, &tv); if (nRet < 0) { printf("select失败 "); break; } if (nRet == 0) /* timed out */ { if (++missed_heartbeats > 3) printf("连续三个心跳未收到,可能服务器已挂 "); printf("心跳未收到 #%d ", missed_heartbeats); tv.tv_sec = T2; continue; } else { for (int i = 0; i < (int)fdSocket.fd_count; i++) { if (FD_ISSET(fdSocket.fd_array[i], &fdRead)) { if (fdSocket.fd_array[i] == serverSocket) { if ((acceptSocket = accept(serverSocket, (sockaddr*)&clientAddress, &addrlen)) == INVALID_SOCKET) { printf("接受客户端连接失败!"); return -1; } ULONG nonblock = 1; if (ioctlsocket(acceptSocket, FIONBIO, &nonblock) == SOCKET_ERROR) { printf("Socket异步配置错误 %d ", WSAGetLastError()); return -1; } FD_SET(acceptSocket, &fdSocket); printf("建立连接成功 "); } else { //nRet--; acceptSocket = fdSocket.fd_array[i]; //char buf[1024]; //int cnt=sizeof(buf); memset(&msg, 0, sizeof(msg)); int bytes; //if ((bytes = recv(acceptSocket, buf, 2, 0)) == SOCKET_ERROR) if ((bytes = recv(acceptSocket, (char *)&msg, sizeof(msg), 0)) == SOCKET_ERROR) { printf("接收数据失败! "); return -1; } if (bytes > 0) { switch (ntohs(msg.type)) { case MSG_TYPE1: case MSG_TYPE2: printf("有消息来自 %s: %s ", inet_ntoa(clientAddress.sin_addr), msg.data); if (send(acceptSocket, (char *)& msg, sizeof(msg_t), 0) == SOCKET_ERROR) { printf("发送数据失败!"); return -1; } missed_heartbeats = 0; tv.tv_sec = T1 + T2; break; case MSG_HEARTBEAT: printf("收到心跳 "); bytes = send(acceptSocket, (char *)&msg, sizeof(msg), 0); if (bytes < 0) { printf("心跳回送失败 "); return -1; } missed_heartbeats = 0; tv.tv_sec = T1 + T2; break; default: printf("未知类型 "); closesocket(fdSocket.fd_array[i]); FD_CLR(fdSocket.fd_array[i], &fdSocket); break; } } else { closesocket(fdSocket.fd_array[i]); FD_CLR(fdSocket.fd_array[i], &fdSocket); } } } } } } //清理套接字占用的资源 WSACleanup(); return 0; }
client
#include <tchar.h> #include <winsock2.h> #include <stdio.h> #include <windows.h> #include <process.h> #pragma comment(lib,"ws2_32.lib") #define PORT 2000 typedef struct /* message structure */ { UINT16 type; char data[1024]; } msg_t; #define MSG_TYPE1 1 /* application specific msg */ #define MSG_TYPE2 2 /* another one */ #define MSG_HEARTBEAT 3 /* heartbeat message */ #define T1 6 /* idle time before heartbeat */ #define T2 1 /* time to wait for response */ DWORD WINAPI listenFunc(PVOID pvParam) { SOCKET sock = *((SOCKET*)pvParam); fd_set fdSocket; FD_ZERO(&fdSocket); FD_SET(sock, &fdSocket); struct timeval tv; tv.tv_sec = T1; tv.tv_usec = 0; int missed_heartbeats = 0; msg_t msg; int length; while (1) { fd_set fdRead = fdSocket; int nRet = select(sock + 1, &fdRead, NULL, NULL, &tv); if (nRet == 0) /* timed out */ { if (++missed_heartbeats > 3) { printf("连续三个心跳未收到,可能服务器已挂 "); } printf("发送心跳 #%d ", missed_heartbeats); msg.type = htons(MSG_HEARTBEAT); if (send(sock, (char*)&msg, sizeof(msg), 0) == SOCKET_ERROR) { printf("发送数据失败!"); return -1; } tv.tv_sec = T2; continue; } else { memset(&msg, 0, sizeof(msg)); int bytes; if ((bytes = recv(sock, (char *)&msg, sizeof(msg), 0)) == SOCKET_ERROR) { printf("接收数据失败! "); return -1; } if (bytes > 0) { switch (ntohs(msg.type)) { case MSG_TYPE1: case MSG_TYPE2: printf("有消息来: %s ", msg.data); break; case MSG_HEARTBEAT: printf("收到心跳 "); break; default: printf("未知类型 "); closesocket(sock); FD_CLR(sock, &fdSocket); break; } missed_heartbeats = 0; tv.tv_sec = T1 + T2; } else { closesocket(sock); FD_CLR(sock, &fdSocket); } } } } int _tmain(int argc, _TCHAR* argv[]) { WSADATA wsa; //初始化套接字DLL if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("套接字初始化失败!"); return -1; } SOCKET sock; if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { printf("创建套接字失败!"); return -1; } //char ipaddr[100]; //printf("请输入对方ip地址:"); //gets(ipaddr); struct sockaddr_in serverAddress; memset(&serverAddress, 0, sizeof(sockaddr_in)); serverAddress.sin_family = AF_INET; serverAddress.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); serverAddress.sin_port = htons(PORT); if (connect(sock, (sockaddr*)&serverAddress, sizeof(serverAddress)) == SOCKET_ERROR) { printf("建立连接失败!"); return -1; } ULONG nonblock = 1; if (ioctlsocket(sock, FIONBIO, &nonblock) == SOCKET_ERROR) { printf("ioctlsocket() failed with error %d ", WSAGetLastError()); return -1; } _beginthreadex(NULL, 0, (unsigned int(__stdcall *)(void *))listenFunc, &sock, 0, NULL); msg_t msg; memset(&msg, 0, sizeof(msg)); while (true) { gets_s(msg.data); msg.type = htons(MSG_TYPE1); if (send(sock, (char*)&msg, sizeof(msg), 0) == SOCKET_ERROR) { printf("发送数据失败!"); return -1; } } //清理套接字占用的资源 WSACleanup(); return 0; }