以下示例还是实现和前两篇文章(之一&之二)一样的功能:Client端连接Server端,向Server端发送数据。Server端接受Client端发送过来的数据并输出。Server端还是单线程处理多Client端连接的情况。
Server.cpp-----------------------------------------------------------------------------------------
1、在main中创建窗口但不调用ShowWindow即隐藏了窗口。由于是控制函程序,所以还是有控制函窗口的。
2、在ServerSocketProc中去初始化Windows Socket库、创建Socket、绑定Socket、监听Socket。
3、在窗口函数中处理Socket相关的消息
4、Client端通过closesocket关闭套接字会进入到以下的FD_CLOSE事件输出:"FD_CLOSE"
而直接关闭Client端会使WSAGETSELECTERROR(lParam)为真,也就会输出:"WSAGETSELECTERROR get error"
#include <windows.h> #include <iostream> using namespace std; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int ServerSocketProc(HWND); #pragma comment(lib, "Ws2_32.lib") #define WM_SOCKET WM_USER + 100 #define PORT_NO 6000 #define BACKLOG 10 // 全局变量 SOCKET gSockSrv; int main() { static TCHAR lpszAppName[] = TEXT("TestWin"); HWND hwnd; MSG msg; WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = NULL; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = lpszAppName; // 注册窗口类 if (!RegisterClass(&wc)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), lpszAppName, MB_ICONERROR); return 0; } // 创建应用程序主窗口 hwnd = CreateWindow(lpszAppName, TEXT("Server"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL); if (NULL == hwnd) { MessageBox(NULL, TEXT("CreateWindow failed."), lpszAppName, MB_ICONERROR); return 0; } // 创建Socket服务 int ret = ServerSocketProc(hwnd); if (0 != ret) { MessageBox(NULL, TEXT("ServerSocketProc failed."), lpszAppName, MB_ICONERROR); return 0; } // 消息循环 while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } // 清理资源------ closesocket(gSockSrv); WSACleanup(); return msg.wParam; } // // 窗口过程函数 // LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_SOCKET: // 处理Socket信息 { int ret; SOCKET sock = wParam; // 查看是否出错 if(WSAGETSELECTERROR(lParam)) { closesocket(sock); cout << "WSAGETSELECTERROR get error" << endl; if (sock == gSockSrv) { DestroyWindow(hwnd); } return 0; } // 处理发生的事件 switch(WSAGETSELECTEVENT(lParam)) { case FD_ACCEPT: // 监听中的套接字检测到有连接进入 { int len=sizeof(SOCKADDR); SOCKADDR_IN addrClient; SOCKET sockConn = accept(sock, (SOCKADDR*)&addrClient, &len); if (INVALID_SOCKET == sockConn) { cout << "accept() failed:" << WSAGetLastError() << endl; return 0; } cout << "接受到新连接:" << inet_ntoa(addrClient.sin_addr) << endl; WSAAsyncSelect(sockConn, hwnd, WM_SOCKET, FD_READ | FD_WRITE | FD_CLOSE); } break; case FD_WRITE: { } break; case FD_READ: { char recvBuffer[MAX_PATH] = {0}; ret = recv(sock, recvBuffer, sizeof(recvBuffer), 0); if (ret == 0) { cout << "Connection has been gracefully closed." << endl; closesocket(sock); return 0; } else if (ret == SOCKET_ERROR) { cout << "Connection has been closed ungracefully." << endl; closesocket(sock); return 0; } cout << "Receive Data from Client:" << recvBuffer << endl; } break; case FD_CLOSE: { cout << "FD_CLOSE" << endl; closesocket(sock); } break; } } break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); } int ServerSocketProc(HWND hwnd) { cout << "ServerSocketProc-----------------------------------------BEG" << endl; WSADATA wsaData; int ret; WORD wVersionRequested = MAKEWORD(2, 2); SOCKET sockSrv; SOCKADDR_IN addrSrv; HANDLE hThread = NULL; // 初始化Windows Socket------ ret = WSAStartup(wVersionRequested, &wsaData); if (ret != 0) { cout << "WSAStartup() failed:" << WSAGetLastError() << endl; return -1; } // 创建Socket------ sockSrv = socket(AF_INET, SOCK_STREAM, 0); if (INVALID_SOCKET == sockSrv) { cout << "socket() failed:" << WSAGetLastError() << endl; WSACleanup(); return -1; } gSockSrv = sockSrv; addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(PORT_NO); // Bind Socket------ ret = bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); if (SOCKET_ERROR == ret) { cout << "bind() failed:" << WSAGetLastError() << endl; closesocket(sockSrv); WSACleanup(); return -1; } // 监听------ ret = listen(sockSrv, BACKLOG); if (SOCKET_ERROR == ret) { cout << "listen() failed:" << WSAGetLastError() << endl; closesocket(sockSrv); WSACleanup(); return -1; } // WSAAsyncSelect------ WSAAsyncSelect(sockSrv, hwnd, WM_SOCKET, FD_ACCEPT | FD_CLOSE); cout << "ServerSocketProc-----------------------------------------END" << endl; cout<< "Server started......" << endl; return 0; }
#include <iostream> #include <windows.h> using namespace std; #pragma comment(lib, "Ws2_32.lib") #define PORT_NO 6000 #define SRV_IP_ADDR "127.0.0.1" int main(int argc, char* argv[]) { int ret; WSADATA wsaData; WORD wVersionRequested = MAKEWORD(2, 2); SOCKET sockClient; SOCKADDR_IN addrSrv; // 初始化Windows Socket------ ret = WSAStartup(wVersionRequested, &wsaData); if (ret != 0) { cout << "WSAStartup() failed:" << WSAGetLastError() << endl; return -1; } // 创建Socket------ sockClient = socket(AF_INET, SOCK_STREAM, 0); if (INVALID_SOCKET == sockClient) { cout << "socket() failed:" << WSAGetLastError() << endl; WSACleanup(); return -1; } addrSrv.sin_addr.S_un.S_addr = inet_addr(SRV_IP_ADDR); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(PORT_NO); // 连接------ ret = connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); if (SOCKET_ERROR == ret) { cout << "connect() failed:" << WSAGetLastError() << endl; closesocket(sockClient); WSACleanup(); return -1; } else { cout << "connect() successfully." << endl; } // 发送数据------ char sendBuf[MAX_PATH] = {0}; while (1) { cin.getline(sendBuf, sizeof(sendBuf)); if (strcmp(sendBuf, "exit") == 0) { break; } ret = send(sockClient, sendBuf, strlen(sendBuf)+1, 0); if (SOCKET_ERROR == ret) { cout << "send() failed:" << WSAGetLastError() << endl; closesocket(sockClient); WSACleanup(); return -1; } } // 清理资源------- closesocket(sockClient); WSACleanup(); cout << "exit..." << endl; return 0; }