以纯重叠I/O方式实现回声服务器端(windows)
服务器端:
#include <stdio.h> #include <stdlib.h> #include <winsock2.h> #define BUF_SIZE 1024 void CALLBACK ReadCompRoutine(DWORD, DWORD, LPWSAOVERLAPPED, DWORD); void CALLBACK WriteCompRoutine(DWORD, DWORD, LPWSAOVERLAPPED, DWORD); void ErrorHanding(char *msg); typedef struct { SOCKET hClntSock; char buf[BUF_SIZE]; WSABUF wsaBuf; } PER_IO_DATA, *LPPER_IO_DATA; int main(int argc, char *argv[]) { WSADATA wsaData; SOCKET hLisnSock, hRecvSock; SOCKADDR_IN lisnAdr, recvAdr; LPWSAOVERLAPPED lpOvLp; DWORD recvBytes; LPPER_IO_DATA hbInfo; int mode = 1, recvAdrSz, flagInfo = 0; if (argc != 2) { printf("Usage: %s <port>\n", argv[0]); exit(1); } if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) ErrorHanding("WSAStartUp() error!"); hLisnSock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); ioctlsocket(hLisnSock, FIONBIO, (u_long *)&mode); // for non-blocking mode socket memset(&lisnAdr, 0, sizeof(lisnAdr)); lisnAdr.sin_family = AF_INET; lisnAdr.sin_addr.s_addr = htonl(INADDR_ANY); lisnAdr.sin_port = htons(atoi(argv[1])); if (bind(hLisnSock, (SOCKADDR *)&lisnAdr, sizeof(lisnAdr)) == SOCKET_ERROR) ErrorHanding("bind() error"); if (listen(hLisnSock, 5) == SOCKET_ERROR) ErrorHanding("listen() error"); recvAdrSz = sizeof(recvAdr); while (1) { SleepEx(100, TRUE); // for alertable wait state hRecvSock = accept(hLisnSock, (SOCKADDR *)&recvAdr, &recvAdrSz); if (hRecvSock == INVALID_SOCKET) { if (WSAGetLastError() == WSAEWOULDBLOCK) continue; else ErrorHanding("accept() error"); } puts("Client connected ....."); lpOvLp = (LPWSAOVERLAPPED)malloc(sizeof(WSAOVERLAPPED)); memset(lpOvLp, 0, sizeof(WSAOVERLAPPED)); hbInfo = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA)); hbInfo->hClntSock = (DWORD)hRecvSock; (hbInfo->wsaBuf).buf = hbInfo->buf; (hbInfo->wsaBuf).len = BUF_SIZE; lpOvLp->hEvent = (HANDLE)hbInfo; WSARecv(hRecvSock, &(hbInfo->wsaBuf), 1, &recvBytes, (LPDWORD)&flagInfo, lpOvLp, ReadCompRoutine); } closesocket(hRecvSock); closesocket(hLisnSock); WSACleanup(); return 0; } // end of main function void CALLBACK ReadCompRoutine(DWORD dwError, DWORD szRecvBytes, LPWSAOVERLAPPED lpOverlapped, DWORD flags) { LPPER_IO_DATA hbInfo = (LPPER_IO_DATA)(lpOverlapped->hEvent); SOCKET hSock = hbInfo->hClntSock; LPWSABUF bufInfo = &(hbInfo->wsaBuf); DWORD sendBytes; if (szRecvBytes == 0) { closesocket(hSock); free(lpOverlapped->hEvent); free(lpOverlapped); puts("Client disconnected ....."); } else // echo! { bufInfo->len = szRecvBytes; WSASend(hSock, bufInfo, 1, &sendBytes, 0, lpOverlapped, WriteCompRoutine); } } void CALLBACK WriteCompRoutine(DWORD dwError, DWORD szSendBytes, LPWSAOVERLAPPED lpOverlapped, DWORD flags) { LPPER_IO_DATA hbInfo = (LPPER_IO_DATA)(lpOverlapped->hEvent); SOCKET hSock = hbInfo->hClntSock; LPWSABUF bufInfo = &(hbInfo->wsaBuf); DWORD recvBytes; int flagInfo = 0; WSARecv(hSock, bufInfo, 1, &recvBytes, (LPDWORD)&flagInfo, lpOverlapped, ReadCompRoutine); } void ErrorHanding(char *msg) { fputs(msg, stderr); fputc('\n', stderr); exit(1); }
客户端:
#include <stdio.h> #include <stdlib.h> #include <winsock2.h> #define BUF_SIZE 1024 void ErrorHandling(char *message); int main(int argc, char *argv[]) { WSADATA wsaData; SOCKET hSocket; SOCKADDR_IN servAdr; char message[BUF_SIZE]; int strLen, readLen; if (argc != 3) { printf("Usage: %s <IP> <port>\n", argv[0]); exit(1); } if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) ErrorHandling("WSAStartup() error!"); hSocket = socket(PF_INET, SOCK_STREAM, 0); if (hSocket == INVALID_SOCKET) ErrorHandling("socket() error"); memset(&servAdr, 0, sizeof(servAdr)); servAdr.sin_family = AF_INET; servAdr.sin_addr.s_addr = inet_addr(argv[1]); servAdr.sin_port = htons(atoi(argv[2])); if (connect(hSocket, (SOCKADDR *)&servAdr, sizeof(servAdr)) == SOCKET_ERROR) ErrorHandling("connect() error!"); else puts("Connected .........."); while (1) { fputs("Input message(Q to quit): ", stdout); fgets(message, BUF_SIZE, stdin); if(!strcmp(message, "q\n") || !strcmp(message, "Q\n")) break; strLen = strlen(message); send(hSocket, message, strLen, 0); readLen = 0; while (1) { readLen += recv(hSocket, &message[readLen], BUF_SIZE - 1, 0); if (readLen >= strLen) break; } message[strLen] = 0; printf("Message from server: %s", message); } closesocket(hSocket); WSACleanup(); return 0; } void ErrorHandling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); }