Здравствуйте,
по просьбам трудящихся, subj. Пример простейший, просто, как говорится "для примера"
.
Багов не заметил.. Проверял много раз, работает
Выход по Ctrl+C, сервер слушает 5678 порт на всех интерфейсах.
#include <iostream>
#include <winsock2.h>
#include <windows.h>
#pragma comment (lib, "ws2_32.lib")
const int SERVER_PORT = 5678;
const int BUF_SIZE = 65535;
BOOL WINAPI HandlerRoutine(DWORD);
int main (void)
{
using std::cout;
using std::endl;
using std::cerr;
WSADATA wd;
WSAEVENT hEvents[3];
SOCKET sock, lsock, tsock;
WSANETWORKEVENTS wsEvents;
SOCKADDR_IN saddr;
DWORD dwDone = 0, dwCount;
int nRet, nSize;
char buf[BUF_SIZE];
if(nRet = WSAStartup(MAKEWORD(2,0), &wd)){
cerr << "WSAStartup fail with code " << nRet << endl;
return -1;
}
hEvents[0] = static_cast<WSAEVENT>(CreateEvent(NULL, true, false, "StopProgrammEvent"));
if(!hEvents[0]){
cerr << "WSACreateEvent[1] fail with code " << GetLastError () << endl;
return -2;
}
SetConsoleCtrlHandler(HandlerRoutine, true);
hEvents[1] = WSACreateEvent();
if (!hEvents[1]){
cerr << "WSACreateEvent[0] fail with code " << WSAGetLastError() << endl;
return -3;
}
hEvents[2] = WSACreateEvent();
if(!hEvents[2]){
cerr << "WSACreateEvent[2] fail with code " << WSAGetLastError() << endl;
return -4;
}
lsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(lsock == INVALID_SOCKET){
cerr << "socket fail with code " << WSAGetLastError () << endl;
return -5;
}
ZeroMemory(&saddr, sizeof (SOCKADDR_IN));
saddr.sin_family = AF_INET;
saddr.sin_port = htons (SERVER_PORT);
saddr.sin_addr.s_addr = INADDR_ANY;
if(bind(lsock, reinterpret_cast<SOCKADDR*>(&saddr),sizeof(SOCKADDR_IN)))
{
cerr << "bind fail with code " << WSAGetLastError () << endl;
return -6;
}
if(listen(lsock, 100)){
cerr << "listen fail with code " << WSAGetLastError () << endl;
return -7;
}
cout << "Server listen port " << SERVER_PORT << " on " << inet_ntoa (saddr.sin_addr) << endl;
if(WSAEventSelect(lsock, hEvents[1], FD_ACCEPT)){
cerr << "WSAEventSelect fail with code " << WSAGetLastError () << endl;
return -8;
}
dwCount = 2;
while(!dwDone){
nRet = WSAWaitForMultipleEvents(dwCount, hEvents, false, WSA_INFINITE, false);
switch (nRet){
case 0:
cout << "StopProgrammEvent signaled.. Stopping.." << endl;
dwDone = 1;
break;
case 1:
if(!WSAEnumNetworkEvents(lsock, hEvents[1], &wsEvents)){
if (wsEvents.iErrorCode[FD_ACCEPT_BIT]){
cerr << "FD_ACCEPT fail. Stopping.." << endl;
dwDone = 1;
break;
}
nSize = sizeof(SOCKADDR_IN);
tsock = accept(lsock, reinterpret_cast<SOCKADDR*>(&saddr), &nSize);
if(tsock == INVALID_SOCKET){
cerr << "accept fail with code " << WSAGetLastError () << endl;
break;
}
cout << "Client connection from: " << inet_ntoa (saddr.sin_addr) << endl;
if(dwCount > 2 ){
cout << "Connection limit exceeded. Closed." << endl;
closesocket (tsock);
} else {
if (WSAEventSelect(tsock, hEvents[2], FD_READ | FD_CLOSE)){
cerr << "WSAEventSelect fail with code " << WSAGetLastError () << endl;
cerr << "Stopping.." << endl;
dwDone = 1;
break;
}
sock = tsock;
dwCount = 3;
}
} else {
cerr << "WSAEnumNetworkEvent fail with code " << WSAGetLastError () << endl;
ResetEvent (hEvents[1]);
}
break;
case 2:
if(!WSAEnumNetworkEvents(sock, hEvents[2], &wsEvents)){
if(wsEvents.lNetworkEvents & FD_READ){
if(wsEvents.iErrorCode[FD_READ_BIT]){
cerr << "FD_READ fail. Stopping.." << endl;
dwDone = 1;
break;
} else {
nRet = recv(sock, buf, BUF_SIZE, 0);
if(nRet > 0) cout << "Received " << nRet << "bytes" << endl;
}
}
if(wsEvents.lNetworkEvents & FD_CLOSE){
if(wsEvents.iErrorCode[FD_CLOSE_BIT]){
cerr << "FD_CLOSE fail with code " << wsEvents.iErrorCode[FD_CLOSE_BIT] << endl;
if(wsEvents.iErrorCode[FD_CLOSE_BIT] == WSAENETDOWN){
cerr << "Stopping.." << endl;
dwDone = 1;
break;
}
} else {
cout << "Client disconnected." << endl;
WSAEventSelect(sock, hEvents[2], 0);
shutdown(sock, SD_BOTH);
closesocket (sock);
dwCount = 2;
}
}
} else {
cerr << "WSAEnumNetworkEvent fail with code " << WSAGetLastError() << endl;
WSAResetEvent(hEvents[2]);
}
break;
default:
cerr << "WSAWaitForMultipleEvents return " << nRet <<" with error code "
<< WSAGetLastError() << endl;
}
}
if (dwCount == 3){
WSAEventSelect(sock, hEvents[2], 0);
shutdown(sock, SD_BOTH);
closesocket(sock);
}
WSAEventSelect(lsock, hEvents[1], 0);
for (dwCount = 3; dwCount > 0; dwCount--)
WSACloseEvent(hEvents[dwCount-1]);
closesocket(lsock);
WSACleanup();
return 0;
}
BOOL WINAPI HandlerRoutine(DWORD)
{
HANDLE hEvent;
hEvent = OpenEvent(EVENT_ALL_ACCESS, false, "StopProgrammEvent");
if(hEvent){
SetEvent(hEvent);
CloseHandle(hEvent);
return true;
}
return false;
}