2011年9月8日
#
WSAAsynSelect的基本使用,下面是一个简单的例子 #include <windows.h> #include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define LISTEN_PORT 5080 #define UWM_SOCKET WM_USER+1
TCHAR szClassName[] = TEXT("WSAAsynSelectClass"); TCHAR szWndName[] = TEXT("WSAAsynSelectWnd");
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam,LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { WNDCLASS wndClass = {0}; HWND hMainWnd;
MSG msg; WSADATA wsaData; int ret; SOCKET listen_sock; TCHAR szErrorMsg[256]; SOCKADDR_IN listen_addr;
ret = WSAStartup(MAKEWORD(2,2), &wsaData); if(0 != ret) { wsprintf(szErrorMsg, TEXT("WSAStartup failed. Error:%d.\n"), WSAGetLastError()); MessageBox(NULL, szErrorMsg, szWndName, MB_OK); return ret; }
listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(INVALID_SOCKET == listen_sock) { wsprintf(szErrorMsg, TEXT("socket failed, Error:%d.\n"), WSAGetLastError()); MessageBox(NULL, szErrorMsg, szWndName, MB_OK); goto rettag1; }
listen_addr.sin_family = AF_INET; listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); listen_addr.sin_port = htons(LISTEN_PORT); ret = bind(listen_sock, (SOCKADDR*)&listen_addr, sizeof(listen_addr)); if(SOCKET_ERROR == ret) { wsprintf(szErrorMsg, TEXT("bind failed. Error:%d.\n"), WSAGetLastError()); MessageBox(NULL, szErrorMsg, szWndName, MB_OK); goto rettag2; }
wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hbrBackground = GetStockObject(WHITE_BRUSH); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hInstance = hInstance; wndClass.lpfnWndProc = MainWndProc; wndClass.lpszClassName = szClassName; wndClass.lpszMenuName = NULL;
if(!RegisterClass(&wndClass)) { wsprintf(szErrorMsg, TEXT("RegisterClass failed.")); MessageBox(NULL, szErrorMsg, szWndName, MB_OK); goto rettag2; }
hMainWnd = CreateWindow(szClassName, szWndName, WS_OVERLAPPEDWINDOW | WS_VSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if(NULL == hMainWnd) { wsprintf(szErrorMsg, TEXT("CreateWindow failed.")); MessageBox(NULL, szErrorMsg, szWndName, MB_OK); UnregisterClass(szClassName, hInstance); goto rettag2; }
ShowWindow(hMainWnd, nShowCmd); UpdateWindow(hMainWnd);
ret = WSAAsyncSelect(listen_sock, hMainWnd, UWM_SOCKET, FD_ACCEPT|FD_CLOSE); if(SOCKET_ERROR == ret) { wsprintf(szErrorMsg, TEXT("WSAAsyncSelect failed. Error:%d.\n"), WSAGetLastError()); MessageBox(NULL, szErrorMsg, szWndName, MB_OK); goto rettag2; }
ret = listen(listen_sock, 5); if(SOCKET_ERROR == ret) { wsprintf(szErrorMsg, TEXT("listen failed. Error:%d.\n"), WSAGetLastError()); MessageBox(NULL, szErrorMsg, szWndName, MB_OK); goto rettag2; }
while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
rettag2: closesocket(listen_sock); rettag1: WSACleanup();
return 0; }
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam,LPARAM lParam) { TCHAR szErrorMsg[256]; char szMsg[256]; SOCKET client_sock = INVALID_SOCKET; SOCKADDR_IN client_addr; int client_addr_len = sizeof(client_addr); int ret; HDC hdc; static int row = 0; TEXTMETRIC textMetric; int textHeight = 5;
hdc = GetDC(hwnd); GetTextMetrics(hdc, &textMetric); textHeight = textMetric.tmHeight;
switch(uMsg) { case WM_DESTROY: ReleaseDC(hwnd, hdc); PostQuitMessage(0); break; case UWM_SOCKET: if(WSAGETSELECTERROR(lParam)) { wsprintf(szErrorMsg, TEXT("WSAGETSELECTERROR failed. Error:%d.\n"), WSAGETSELECTERROR(lParam)); MessageBox(NULL, szErrorMsg, szWndName, MB_OK); break; }
switch(WSAGETSELECTEVENT(lParam)) { case FD_ACCEPT: client_sock = accept(wParam, (SOCKADDR*)&client_addr, &client_addr_len); if(INVALID_SOCKET == client_sock) { wsprintf(szErrorMsg, TEXT("accept failed. Error:%d.\n"), WSAGetLastError()); MessageBox(NULL, szErrorMsg, szWndName, MB_OK); break; }
sprintf_s(szMsg, 256, "accept client:%s:%d.", inet_ntoa(client_addr.sin_addr), client_addr.sin_port); // MessageBoxA(NULL, szMsg, "Information", MB_OK); TextOutA(hdc, 0, row, szMsg, strlen(szMsg)); row += textHeight;
ret = WSAAsyncSelect(client_sock, hwnd, UWM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE); if(SOCKET_ERROR == ret) { wsprintf(szErrorMsg, TEXT("WSAAsyncSelect failed. Error:%d.\n"), WSAGetLastError()); MessageBox(NULL, szErrorMsg, szWndName, MB_OK); } break; case FD_READ: ret = recv(wParam, szMsg, 256, 0); if(SOCKET_ERROR == ret) { wsprintf(szErrorMsg, TEXT("recv failed. Error:%d.\n"), WSAGetLastError()); MessageBox(NULL, szErrorMsg, szWndName, MB_OK); break; } else if(0 == ret) { sprintf_s(szMsg, 256, "client closed.\n"); row += textHeight; TextOutA(hdc, 0, row, szMsg, strlen(szMsg)); row += textHeight; break; } else { TextOutA(hdc, 0, row, szMsg, strlen(szMsg)); row += textHeight; } break; case FD_WRITE: break; case FD_CLOSE: closesocket(wParam); break; } break;
default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return TRUE; }
Complete Routine的基本使用,下面是一个简单的例子 #include <winsock2.h> #include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define LISTEN_PORT 5080 #define BUFF_SIZE 256
void CALLBACK WorkerRoutine(DWORD error, DWORD bytes_transferred, LPWSAOVERLAPPED overlapped, DWORD inflags);
typedef struct { WSAOVERLAPPED overlapped; DWORD recv_bytes; SOCKET client_sock; DWORD inflags; WSABUF buff; }SOCKINFO;
int main(void) { WSADATA wsaData; int nRet; SOCKET listen_sock; SOCKADDR_IN listen_addr; SOCKET client_sock; SOCKADDR_IN client_addr; int client_addr_len = sizeof(client_addr); char buff[BUFF_SIZE]; DWORD recv_bytes = 0; int index; SOCKINFO sockInfo; WSAEVENT wsaEvent;
nRet = WSAStartup(MAKEWORD(2,2), &wsaData); if(0 != nRet) { printf("WSAStartup() failed, error:%d.\n", WSAGetLastError()); return 1; }
listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(INVALID_SOCKET == listen_sock) { printf("socket() failed, error:%d.\n", WSAGetLastError()); goto retflag1; }
listen_addr.sin_family = AF_INET; listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); listen_addr.sin_port = htons(LISTEN_PORT); nRet = bind(listen_sock, (SOCKADDR*)&listen_addr, sizeof(listen_addr)); if(nRet == SOCKET_ERROR) { printf("bind() failed, error:%d.\n", WSAGetLastError()); closesocket(listen_sock); goto retflag1; }
nRet = listen(listen_sock, 5); if(SOCKET_ERROR == nRet) { printf("listen() failed, error:%d.\n", WSAGetLastError()); closesocket(listen_sock); goto retflag1; }
client_sock = accept(listen_sock, (SOCKADDR*)&client_addr, &client_addr_len); if(INVALID_SOCKET == client_sock) { printf("accept failed, error:%d.\n", WSAGetLastError()); closesocket(listen_sock); goto retflag1; }
sockInfo.inflags = 0; memset(&sockInfo.overlapped, 0, sizeof(sockInfo.overlapped)); sockInfo.client_sock = client_sock; sockInfo.buff.buf = buff; sockInfo.buff.len = BUFF_SIZE;
sockInfo.overlapped.hEvent = (HANDLE)&sockInfo;
if(WSARecv(client_sock, &sockInfo.buff, 1, &sockInfo.recv_bytes, &sockInfo.inflags, &sockInfo.overlapped, WorkerRoutine) == SOCKET_ERROR) { if(WSAGetLastError() == WSA_IO_PENDING) { printf("WSARecv() WSA_IO_PENDING.\n"); } else { printf("WSARecv failed, error:%d.\n", WSAGetLastError()); closesocket(listen_sock); closesocket(client_sock); goto retflag1; } }
wsaEvent = WSACreateEvent(); if(WSA_INVALID_EVENT == wsaEvent) { printf("WSACreateEvent() failed, error:%d.\n", WSAGetLastError()); closesocket(listen_sock); closesocket(client_sock); goto retflag1; }
while(1) { index = WSAWaitForMultipleEvents(1, &wsaEvent, FALSE, WSA_INFINITE, TRUE); if(index = WAIT_IO_COMPLETION) { continue; } else { printf("WSAWaitForMultipleEvents() failed, error:%d.\n", WSAGetLastError()); closesocket(listen_sock); closesocket(client_sock); WSACloseEvent(wsaEvent); goto retflag1; } }
closesocket(listen_sock); closesocket(client_sock); WSACloseEvent(wsaEvent);
retflag1: nRet = WSACleanup(); if(0 != nRet) { printf("WSACleanup() failed, error:%d.\n", WSAGetLastError()); return 1; } return 0; }
void CALLBACK WorkerRoutine(DWORD error, DWORD bytes_transferred, LPWSAOVERLAPPED overlapped, DWORD inflags) { SOCKINFO* sockInfo = NULL; if(error != 0) { printf("Callback error:%d.\n", error); return; } if(bytes_transferred == 0) { printf("peer closed.\n"); return; }
sockInfo = (SOCKINFO*)overlapped->hEvent; printf("%s", sockInfo->buff.buf); sockInfo->inflags = 0; memset(&sockInfo->overlapped, 0, sizeof(sockInfo->overlapped)); sockInfo->overlapped.hEvent = (HANDLE)sockInfo;
if(WSARecv(sockInfo->client_sock, &sockInfo->buff, 1, &sockInfo->recv_bytes, &sockInfo->inflags, &sockInfo->overlapped, WorkerRoutine) == SOCKET_ERROR) { if(WSAGetLastError() == WSA_IO_PENDING) { printf("WSARecv() WSA_IO_PENDING.\n"); } else { printf("WSARecv failed, error:%d.\n", WSAGetLastError()); return; } }
}
Windows网络编程Overlapped Event基本使用,下面是一个简单的例子 #include <winsock2.h> #include <windows.h> #include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define LISTEN_PORT 5080 #define BUFF_SIZE 256
int main(void) { WSADATA wsaData; int nRet; SOCKET listen_sock; SOCKADDR_IN listen_addr; SOCKET client_sock; SOCKADDR_IN client_addr; int client_addr_len = sizeof(client_addr); WSAEVENT read_event; WSAOVERLAPPED client_overlapped; char buff[BUFF_SIZE]; WSABUF wsaBuf; int recv_bytes = 0; DWORD flags = 0; DWORD index;
nRet = WSAStartup(MAKEWORD(2,2), &wsaData); if(0 != nRet) { printf("WSAStartup() failed, error:%d.\n", WSAGetLastError()); return 1; }
listen_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if(INVALID_SOCKET == listen_sock) { printf("socket() failed, error:%d.\n", WSAGetLastError()); goto retflag1; }
listen_addr.sin_family = AF_INET; listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); listen_addr.sin_port = htons(LISTEN_PORT); nRet = bind(listen_sock, (SOCKADDR*)&listen_addr, sizeof(listen_addr)); if(nRet == SOCKET_ERROR) { printf("bind() failed, error:%d.\n", WSAGetLastError()); closesocket(listen_sock); goto retflag1; }
nRet = listen(listen_sock, 5); if(SOCKET_ERROR == nRet) { printf("listen() failed, error:%d.\n", WSAGetLastError()); closesocket(listen_sock); goto retflag1; }
client_sock = accept(listen_sock, (SOCKADDR*)&client_addr, &client_addr_len); if(INVALID_SOCKET == client_sock) { printf("accept() failed, error:%d.\n", WSAGetLastError()); closesocket(listen_sock); goto retflag1; }
read_event = WSACreateEvent(); if(WSA_INVALID_EVENT == read_event) { printf("WSACreateEvent() failed, error:%d.\n", WSAGetLastError()); closesocket(listen_sock); closesocket(client_sock); goto retflag1; }
while(1) { memset(&client_overlapped, 0, sizeof(client_overlapped)); client_overlapped.hEvent = read_event;
wsaBuf.buf = buff; wsaBuf.len = BUFF_SIZE;
if(WSARecv(client_sock, &wsaBuf, 1, &recv_bytes, &flags, &client_overlapped, NULL) == SOCKET_ERROR) { if(WSAGetLastError() != WSA_IO_PENDING) { printf("WSARecv failed, error:%d.\n", WSAGetLastError()); } else { printf("WSARecv WSA_IO_PENDING.\n"); } } else { printf("%s", wsaBuf.buf); }
index = WSAWaitForMultipleEvents(1, &read_event, FALSE, WSA_INFINITE, FALSE); while(!WSAResetEvent(read_event)) { printf("WSAResetEvent failed, error:%d.\n", WSAGetLastError()); }
WSAGetOverlappedResult(client_sock, &client_overlapped, &recv_bytes, FALSE, &flags); if(recv_bytes <= 0) { printf("WSAGetOverlappedResult() socket close"); closesocket(client_sock); WSACloseEvent(read_event); break; }
printf("%s", wsaBuf.buf); }
closesocket(listen_sock);
retflag1:
nRet = WSACleanup(); if(0 != nRet) { printf("WSACleanup() failed, error:%d.\n", WSAGetLastError()); return 1; } return 0; }
2011年9月7日
#
下面是使用Completion Port的一个简单的例子: #include <winsock2.h> #include <windows.h> #include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define LISTEN_PORT 5080 #define DATA_BUFSIZE 512
typedef struct { WSAOVERLAPPED wsaOverlapped; WSABUF wsaBuf; char buffer[DATA_BUFSIZE]; }PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;
typedef struct { SOCKET sock; }PER_HANDLE_DATA, *LPPER_HANDLE_DATA;
DWORD WINAPI ServerWorkerThread(LPVOID lpCompletionPortID);
int main() { WSADATA wsaData; int nRet; HANDLE hCompletionPort; SYSTEM_INFO systemInfo; int i; HANDLE hThread; DWORD dwThreadID; SOCKET sockListen; SOCKADDR_IN listenAddr; SOCKET acceptSock; LPPER_HANDLE_DATA perHandleData; LPPER_IO_OPERATION_DATA lpPerIoOperationData; DWORD dwFlags; DWORD dwBytesRecv;
nRet = WSAStartup(MAKEWORD(2,2), &wsaData); if(nRet != 0) { printf("WSAStartup() failed error:%d\n", nRet); return 1; } else printf("WSAStartup is OK!\n");
if((hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL) { printf("CreateIoCompletionPort() failed with error %d.\n", GetLastError()); WSACleanup(); return 1; } else { printf("CreateIoCompletionPort() is OK.\n"); }
GetSystemInfo(&systemInfo); for(i = 0; i < (int)systemInfo.dwNumberOfProcessors*2; ++i) { if((hThread = CreateThread(NULL, 0, ServerWorkerThread, hCompletionPort, 0, &dwThreadID)) == NULL) { printf("CreateThread() failed with error %d.\n", GetLastError()); WSACleanup(); return 1; } else printf("CreateThread() is OK! Thread ID:%d\n", dwThreadID);
CloseHandle(hThread); }
if((sockListen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { printf("WSASocket() failed with error %d.\n", WSAGetLastError()); WSACleanup(); return 1; } else { printf("WSASocket() is OK!\n"); }
listenAddr.sin_family = AF_INET; listenAddr.sin_addr.s_addr = htonl(INADDR_ANY); listenAddr.sin_port = htons(LISTEN_PORT);
if(bind(sockListen, (SOCKADDR*)&listenAddr, sizeof(listenAddr)) == SOCKET_ERROR) { printf("bind() failed, error:%d.\n", WSAGetLastError()); closesocket(sockListen); WSACleanup(); return 1; } else printf("bind()is fine!\n");
if(listen(sockListen, 5) == SOCKET_ERROR) { printf("listen() failed, error:%d.\n", WSAGetLastError()); closesocket(sockListen); WSACleanup(); return 1; } else { printf("listen() is OK!"); }
while(TRUE) { if((acceptSock = WSAAccept(sockListen, NULL, NULL, NULL, 0)) == SOCKET_ERROR) { printf("WSAAccept() failed, error:%d.\n", WSAGetLastError()); WSACleanup(); return 1; } else { printf("WSAAccept() is OK!.\n"); }
if((perHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA))) == NULL) { printf("GlobalAlloc() failed, error:%d.\n", GetLastError()); WSACleanup(); return 1; } else { printf("GlobalAlloc() for PER_HANDLE_DATA is OK!.\n"); }
printf("socket %d create.\n", acceptSock); perHandleData->sock = acceptSock;
if(CreateIoCompletionPort((HANDLE)acceptSock, hCompletionPort, (DWORD)perHandleData, 0) == NULL) { printf("CreateIoCompletionPort() failed, error:%d.\n", GetLastError()); return 1; } else { printf("CreateIoCompletionPort() is OK!.\n"); }
if((lpPerIoOperationData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA))) == NULL) { printf("GlobalAlloc() failed, error:%d.\n", GetLastError()); return 1; } else { printf("GlobalAlloc() for PER_IO_OPERATION_DATA is OK!\n"); }
ZeroMemory(&(lpPerIoOperationData->wsaOverlapped), sizeof(OVERLAPPED)); lpPerIoOperationData->wsaBuf.len = DATA_BUFSIZE; lpPerIoOperationData->wsaBuf.buf = lpPerIoOperationData->buffer;
dwFlags = 0; if(WSARecv(acceptSock, &(lpPerIoOperationData->wsaBuf), 1, &dwBytesRecv, &dwFlags, &(lpPerIoOperationData->wsaOverlapped), NULL) == SOCKET_ERROR) { if(WSAGetLastError() != ERROR_IO_PENDING) { printf("WSARecv() failed, error %d\n", WSAGetLastError()); WSACleanup(); return 1; } } else { printf("WSARecv() is OK!\n"); } }
if(WSACleanup() == SOCKET_ERROR) { printf("WSACleanup() failed, error:%d.\n", WSAGetLastError()); } else { printf("WSACleanup() is OK!.\n"); } }
DWORD WINAPI ServerWorkerThread(LPVOID lpCompletionPortID) { HANDLE hCompletionPort = (HANDLE)lpCompletionPortID; DWORD dwBytesTransferred = 0; LPPER_HANDLE_DATA lpPerHandleData; LPPER_IO_OPERATION_DATA lpPerIoData; DWORD dwFlags;
while(TRUE) { if(GetQueuedCompletionStatus(hCompletionPort, &dwBytesTransferred, (DWORD*)&lpPerHandleData, (LPOVERLAPPED*)&lpPerIoData, INFINITE) == 0) { printf("GetQueuedCompletionStatus() failed, error:%d.\n", GetLastError()); return 0; } else { printf("GetQueuedCompletionStatus() is OK!.\n"); }
if(dwBytesTransferred == 0) { printf("closing socket %d.\n", lpPerHandleData); if(closesocket(lpPerHandleData->sock) == SOCKET_ERROR) { printf("closesocket() failed with error %d\n", WSAGetLastError()); return 0; } else printf("closesocket() is fine!\n");
GlobalFree(lpPerHandleData); GlobalFree(lpPerIoData); continue; } else { printf("%s", lpPerIoData->buffer);
ZeroMemory(&(lpPerIoData->wsaOverlapped), sizeof(OVERLAPPED)); lpPerIoData->wsaBuf.len = DATA_BUFSIZE; lpPerIoData->wsaBuf.buf = lpPerIoData->buffer;
dwFlags = 0; if(WSARecv(lpPerHandleData->sock, &(lpPerIoData->wsaBuf), 1, &dwBytesTransferred, &dwFlags, &(lpPerIoData->wsaOverlapped), NULL) == SOCKET_ERROR) { if(WSAGetLastError() != ERROR_IO_PENDING) { printf("WSARecv() failed, error %d\n", WSAGetLastError()); return 1; } } else { printf("WSARecv() is OK!\n"); } } } }
2011年8月23日
#
下面是使用 WSAEventSelect的一个简单的例子
#include <winsock2.h> #include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define LISTEN_PORT 5080 #define BUFF_SIZE 256
int main(void) { WSADATA wsaData; int nRet; SOCKET listen_sock; SOCKADDR_IN listen_addr; WSAEVENT startEvent; WSAEVENT clientEvent; SOCKET client_sock; int event_num = 0; int index; SOCKADDR_IN client_addr; int client_addr_len = sizeof(client_addr); WSANETWORKEVENTS wsaNetworkEvents; WSAEVENT event_array[WSA_MAXIMUM_WAIT_EVENTS]; SOCKET sock_array[WSA_MAXIMUM_WAIT_EVENTS]; char buff[BUFF_SIZE]; int accept_num = 0;
nRet = WSAStartup(MAKEWORD(2,2), &wsaData); if(0 != nRet) { printf("WSAStartup() failed, error:%d.\n", WSAGetLastError()); return 1; }
listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(INVALID_SOCKET == listen_sock) { printf("socket() failed, error:%d.\n", WSAGetLastError()); goto rettag1; }
listen_addr.sin_family = AF_INET; listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); listen_addr.sin_port = htons(LISTEN_PORT); nRet = bind(listen_sock, (SOCKADDR*)&listen_addr, sizeof(listen_addr)); if(nRet == SOCKET_ERROR) { printf("bind() failed, error:%d.\n", WSAGetLastError()); closesocket(listen_sock); goto rettag1; }
nRet = listen(listen_sock, 5); if(SOCKET_ERROR == nRet) { printf("listen() failed, error:%d.\n", WSAGetLastError()); closesocket(listen_sock); goto rettag1; }
startEvent = WSACreateEvent(); if (startEvent == WSA_INVALID_EVENT) { printf("WSACreateEvent() failed, error:%d.\n", WSAGetLastError()); closesocket(listen_sock); goto rettag1; }
nRet = WSAEventSelect(listen_sock, startEvent, FD_ACCEPT|FD_CLOSE); if(SOCKET_ERROR == nRet) { printf("WSAEventSelect() failed, error:%d.\n", WSAGetLastError()); WSACloseEvent(startEvent); closesocket(listen_sock); goto rettag1; }
event_array[event_num] = startEvent; sock_array[event_num] = listen_sock; ++event_num;
while(1) { index = WSAWaitForMultipleEvents(event_num, event_array, FALSE, WSA_INFINITE, FALSE); if(index == WSA_WAIT_FAILED || index == WSA_WAIT_TIMEOUT) continue;
index -= WSA_WAIT_EVENT_0; nRet = WSAEnumNetworkEvents(sock_array[index], event_array[index], &wsaNetworkEvents); if(SOCKET_ERROR == nRet) { printf("WSAEnumNetworkEvents() failed, error:%d.\n", WSAGetLastError()); continue; }
if(wsaNetworkEvents.lNetworkEvents & FD_ACCEPT) { if(wsaNetworkEvents.iErrorCode[FD_ACCEPT_BIT] != 0) { printf("FD_ACCEPT error:%d.\n", wsaNetworkEvents.iErrorCode[FD_ACCEPT_BIT]); continue; }
if(event_num >= WSA_MAXIMUM_WAIT_EVENTS) { continue; }
client_sock = accept(sock_array[index], (SOCKADDR*)&client_addr, &client_addr_len); if(INVALID_SOCKET == client_sock) { printf("in accept failed, error:%d.\n", WSAGetLastError()); continue; }
clientEvent = WSACreateEvent(); if(clientEvent == WSA_INVALID_EVENT) { printf("in WSACreateEvent() failed, error:%d.\n", WSAGetLastError()); closesocket(client_sock); continue; }
nRet = WSAEventSelect(client_sock, clientEvent, FD_READ|FD_WRITE|FD_CLOSE); if(SOCKET_ERROR == nRet) { printf("in WSAEventSelect() failed, error:%d.\n", WSAGetLastError()); closesocket(client_sock); continue; }
event_array[event_num] = clientEvent; sock_array[event_num] = client_sock; ++event_num;
++accept_num; } else if(wsaNetworkEvents.lNetworkEvents & FD_READ) { if(wsaNetworkEvents.iErrorCode[FD_READ_BIT] != 0) { printf("FD_READ error:%d.\n", wsaNetworkEvents.iErrorCode[FD_READ_BIT]); continue; }
nRet = recv(sock_array[index], buff, BUFF_SIZE, 0); if(nRet == SOCKET_ERROR) { printf("recv() failed, error:%d.\n", WSAGetLastError()); continue; } else if(nRet == 0) { printf("recv() 0.\n"); continue; } else { printf("\t%s", buff); } } else if(wsaNetworkEvents.lNetworkEvents & FD_WRITE) { if(wsaNetworkEvents.iErrorCode[FD_WRITE_BIT] != 0) { printf("FD_WRITE error:%d.\n", wsaNetworkEvents.iErrorCode[FD_WRITE_BIT]); continue; } printf("FD_WRITE do.\n"); } else if(wsaNetworkEvents.lNetworkEvents & FD_CLOSE) { if(wsaNetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0) { printf("FD_CLOSE error:%d.\n", wsaNetworkEvents.iErrorCode[FD_CLOSE_BIT]); } printf("\nFD_CLOSE!\n");
closesocket(sock_array[index]); WSACloseEvent(event_array[index]);
while(index+1 < event_num) { sock_array[index] = sock_array[index+1]; event_array[index] = event_array[index+1]; ++index; } --event_num; if (event_num <= accept_num) break; } }
while(event_num > 0) { closesocket(sock_array[event_num]); WSACloseEvent(event_array[event_num]); --event_num; }
rettag1: nRet = WSACleanup(); if(0 != nRet) { printf("WSACleanup() failed, error:%d.\n", WSAGetLastError()); return 1; }
return 0; }
2011年8月19日
#
client_sockselect的基本使用 函数原型: int select( __in int nfds, __inout fd_set *readfds, __inout fd_set *writefds, __inout fd_set *exceptfds, __in const struct timeval *timeout ); 参数说明: nfds: 与Berkeley 套接字兼容,没有什么作用,忽略 readfds: 检查设置的套接字是否可以读,可以忽略 writefds:检查设置的套接字是否可以写,可以忽略 exceptfds: 检查套接字的错timeout:select等待的时间。NULL:阻塞状态;初始为{0,0}时,立即返回 返回值:返回fd_set中的套接字句柄数;0:等待时间超时; SOCKET_ERROR发生错误,使用WSAGetLastError获得具体的错误代码。 操作fd_set的宏: FD_CLR(s, *set) 从set中移除 FD_ISSET(s, *set) 如果s是set的成员返回非0,否则返回0 FD_SET(s, *set) 把 s添加到set中 FD_ZERO(*set) 初始化set为null
使用select使用的几个步骤 1. 使用FD_ZERO对fd_set结构清空 2. 添加套接字句柄到fd_set中,使用FD_SET宏 3. 调用select 4. 使用FD_ISSET判断是哪个套接字 5. 进行读写操作,然后返回步骤1
下面是一个简单例子
#include <winsock2.h> #include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define LISTEN_PORT 5080 #define RECV_BUFF_SIZE 512
int main(void) { WSADATA wsadata; int ret; SOCKET listen_sock; SOCKET client_sock; SOCKADDR_IN listen_addr; SOCKADDR_IN in_addr; int in_add_len = sizeof(in_addr); fd_set fdread; char recv_buff[RECV_BUFF_SIZE];
ret = WSAStartup(MAKEWORD(2,2), &wsadata); if(0 != ret) { printf("WSAStartup error:%d.\n", WSAGetLastError()); return -1; }
listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(INVALID_SOCKET == listen_sock) { printf("socket error:%d.\n", WSAGetLastError()); goto rettag1; }
listen_addr.sin_family = AF_INET; listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); listen_addr.sin_port = htons(LISTEN_PORT);
ret = bind(listen_sock, (SOCKADDR*)&listen_addr, sizeof(listen_addr)); if(SOCKET_ERROR == ret) { printf("bind error:%d.\n", WSAGetLastError()); goto rettag2; }
ret = listen(listen_sock, 5); if(SOCKET_ERROR == ret) { printf("listen error:%d.\n", WSAGetLastError()); goto rettag2; }
client_sock = accept(listen_sock, (SOCKADDR*)&in_addr, &in_add_len); if(INVALID_SOCKET == client_sock) { printf("accept error:%d.\n", WSAGetLastError()); goto rettag2; } else { printf("accept client:%s:%d.\n", inet_ntoa(in_addr.sin_addr), in_addr.sin_port); }
while(1) { FD_ZERO(&fdread); FD_SET(client_sock, &fdread); ret = select(0, &fdread, NULL, NULL, NULL); if(SOCKET_ERROR == ret) { printf("select error:%d.\n", WSAGetLastError()); } if(ret > 0) { if(FD_ISSET(client_sock, &fdread)) { ret = recv(client_sock, recv_buff, RECV_BUFF_SIZE, 0); if(SOCKET_ERROR == ret) { printf("recv error:%d.\n", WSAGetLastError()); } else if(0 == ret) { printf("recv, socket closed.\n"); break; } else { printf("receive data:\n%s\n", recv_buff); } } } } closesocket(client_sock ); rettag2: ret = closesocket(listen_sock); if(SOCKET_ERROR == ret) { printf("closesocket error:%d.\n", WSAGetLastError()); }
rettag1: ret = WSACleanup(); if(0 != ret) { printf("WSACleanup error:%d.\n", WSAGetLastError()); return -1; }
return 0; }
2011年6月3日
#
摘要: QT没有提供一个完整的IP地址控件,1. 可以使用QLineEdit简单的实现Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> QRegExp regExp("((2[0-4]\\d|25[0-5]|[01]?\\d... 阅读全文
2011年2月17日
#
ACE使用日志回调机制定制日志格式 ACE日志提供ACE_Log_Msg::MSG_CALLBACK标志,启用此标志后,输出日志的之前会调用我们自己定制的函数,对消息数据可以进行进一步处理。 实现CALLBACK函数,需要写一个日志类,派生自ACE_Log_Msg_Callback类,然后重写里面的log虚函数
class Logger : public ACE_Log_Msg_Callback { public: virtual void log(ACE_Log_Record &log_record); };
在日志输出之前,会通过调用我们重写的log函数。源码如下:
ssize_t ACE_Log_Msg::log (ACE_Log_Record &log_record, int suppress_stderr) { // … if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::MSG_CALLBACK) && this->msg_callback () != 0) this->msg_callback ()->log (log_record); // … }
通过上面知道执行日志回调函数的两个条件: 1. 启用ACE_Log_Msg::MSG_CALLBACK 2. 设置我们Logger对象的指针 调用时会传给我们一个ACE_Log_Record引用的对象,这个对象包含输出日志的信息,因此在log函数内部们就可以对日志定制化。注意在在log函数内部使用ACE_DEBUG等会产生无限递归调用。 示例代码:
#include "ace/Log_Msg.h" #include "ace/Log_Msg_Callback.h" #include "ace/Log_Record.h" #include "ace/OS_NS_stdio.h" #include "ace/os.h" class Logger : public ACE_Log_Msg_Callback { public: virtual void log(ACE_Log_Record &log_record); }; int format_time(const ACE_Time_Value& time_tv, ACE_TCHAR* outbuf, size_t bufsize) { if (bufsize == 0) return 0; time_t time_tt = time_tv.sec(); struct tm* time_tm = ACE_OS::localtime(&time_tt); int length = ACE_OS::snprintf( outbuf, bufsize - 1, "%04d-%02d-%02d %02d:%02d:%02d.%03d", time_tm->tm_year+1900, time_tm->tm_mon+1, time_tm->tm_mday, time_tm->tm_hour, time_tm->tm_min, time_tm->tm_sec, time_tv.usec()/1000); return length; } void Logger::log(ACE_Log_Record &log_record) { ACE_TCHAR time_str[32]; // 获取时间格式 ACE_Time_Value now = ACE_OS::gettimeofday(); format_time(now, time_str, 32); // 获取日志等级名称 u_long priority = log_record.priority(); const ACE_TCHAR *priority_name = log_record.priority_name(ACE_Log_Priority(log_record.type())); int data_length = log_record.msg_data_len(); data_length += 4; // [] [] data_length += ACE_OS::strlen(time_str); // [time] data_length += ACE_OS::strlen(priority_name); // [priority name] ACE_TCHAR* new_format_msg; ACE_NEW(new_format_msg, ACE_TCHAR[data_length+1]); const ACE_TCHAR *old_data = log_record.msg_data(); ACE_OS::snprintf(new_format_msg, data_length+1, "[%s][%s]%s", time_str, priority_name, old_data); log_record.msg_data(new_format_msg); } int ACE_TMAIN(int, ACE_TCHAR *[]) { ACE_LOG_MSG->set_flags(ACE_Log_Msg::MSG_CALLBACK); Logger logger; ACE_LOG_MSG->msg_callback(&logger); ACE_DEBUG((LM_DEBUG, "(%t) show message!\n"));
return 0; }
2006年9月25日
#
#include <stdlib.h> #include <iostream.h> void main() { int num = 123; const unsigned int NO = 5; // 如果将这两条语句改为 char *cNum = " ";在执行程序时候将会产生 char cNum[NO]; // 严重的错误而终止. itoa(num, cNum, 10); cout<<cNum<<endl; }
使用 const unsigned int NO = 5; char cNum[NO]; NO 的大小可以随意改.为什么? 为什么不可用指针类型的参数传给itoa() 的第二个参数?
|