Ziehier mijn eerste poging om een multithreaded server te schrijven.
Het probleem is hetvolgende : Wanneer ik met een client (netcat in dit geval) verbind naar de server en text doorstuur, krijg ik onmiddelijk een popup vd server-app met de betreffende text, als ik deze boodschap wegklik, komt hij steeds weer opnieuw terug met dezelfde msg !? (ipv te wachten tot er weer data pending is op de client socket.)
Omdat de buffer (pszTemp) word ge-cleared voor iedere recv() kan de msg niet keer na keer hetzelfde zijn - of de data moet nog steeds pending zijn op de socket...
Moet ik op een of andere manier de socket duidelijk maken dat de data erafgehaald is ???
Korte samenvatting vd code:
In de WM_CREATE word de InitServer() func. aangeroepen, deze bind de m_ServerSocket aan alle locale adapters op poort 8585 en vraagt met AsyncSelect om notification te ontvangen voor incomming connections (FD_ACCEPT).
Bij de accept van de connectie wordt er een nieuwe thread gestart die de client moet verderhelpen. En hier loopt het verkeerd : ioctlsocket beweerd dat er steeds data pending is op de socket.
Wat doe ik verkeerd ???
Iemand ?
Alle hulp is welkom !
De Main Window Proc :
De InitServer() Proc :
En Natuurlijk de Client proc : (deze is niet async.)
Het probleem is hetvolgende : Wanneer ik met een client (netcat in dit geval) verbind naar de server en text doorstuur, krijg ik onmiddelijk een popup vd server-app met de betreffende text, als ik deze boodschap wegklik, komt hij steeds weer opnieuw terug met dezelfde msg !? (ipv te wachten tot er weer data pending is op de client socket.)
Omdat de buffer (pszTemp) word ge-cleared voor iedere recv() kan de msg niet keer na keer hetzelfde zijn - of de data moet nog steeds pending zijn op de socket...
Moet ik op een of andere manier de socket duidelijk maken dat de data erafgehaald is ???
Korte samenvatting vd code:
In de WM_CREATE word de InitServer() func. aangeroepen, deze bind de m_ServerSocket aan alle locale adapters op poort 8585 en vraagt met AsyncSelect om notification te ontvangen voor incomming connections (FD_ACCEPT).
Bij de accept van de connectie wordt er een nieuwe thread gestart die de client moet verderhelpen. En hier loopt het verkeerd : ioctlsocket beweerd dat er steeds data pending is op de socket.
Wat doe ik verkeerd ???
Alle hulp is welkom !
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
| // Custom message to receive notification of socket acitvity (WSAAsyncSelect)
#define WM_SOCKET_NOTIFY WM_USER + 1
// struct for passing data between main program and client threads
typedef struct
{
SOCKET socket;
HWND hWnd;
} PARAMS, *PPARAMS;
// The server socket variable
SOCKET m_ServerSocket; |
De Main Window Proc :
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
| LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_SOCKET_NOTIFY:
{
wEvent = WSAGETSELECTEVENT (lParam) ; // ie, LOWORD
wError = WSAGETSELECTERROR (lParam) ; // ie, HIWORD
if (wEvent == FD_ACCEPT)
{
// An incomming connection is pending,
// start a new thread to handle the client
SOCKET theClient;
theClient = accept(m_ServerSocket,
NULL,
NULL);
if (theClient == INVALID_SOCKET)
{
MessageBox(hWnd, _T ("accept error \n"), _T("error"), MB_OK);
WSACleanup();
return 0;
}
parameters.hWnd = hWnd;
parameters.socket = theClient;
_beginthread(ClientProc, 0, ¶meters);
}
}
break;
case WM_CREATE:
InitServer(hWnd);
break;
.....
case WM_DESTROY:
closesocket(m_ServerSocket);
WSACleanup();
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
} |
De InitServer() Proc :
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| void InitServer(HWND hWnd)
{
WSADATA WSAData;
WSAStartup(MAKEWORD(2,0), &WSAData);
m_ServerSocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP) ;
if (m_ServerSocket == INVALID_SOCKET)
{
MessageBeep(MB_OK);
MessageBox(hWnd, _T("Socket creation failed"), _T("error"), MB_OK);
WSACleanup () ;
PostQuitMessage(0);
return;
}
// Async select - notify on incomming connection (FD_ACCEPT)
if (SOCKET_ERROR == WSAAsyncSelect (m_ServerSocket, hWnd, WM_SOCKET_NOTIFY,
FD_ACCEPT))
{
MessageBox(hWnd, _T ("WSAAsyncSelect error \n"), _T("error"), MB_OK);
closesocket(m_ServerSocket) ;
WSACleanup();
PostQuitMessage(0);
return;
}
// Bind the socket to our local server address
SOCKADDR_IN saServer;
saServer.sin_family = AF_INET;
saServer.sin_addr.s_addr = INADDR_ANY; // Bind to all nic's
saServer.sin_port = htons(8585); // Use port 8585
int nRet = bind(m_ServerSocket, (LPSOCKADDR)&saServer, sizeof(struct sockaddr));
if (nRet == SOCKET_ERROR)
{
MessageBox(hWnd, _T ("bind error \n"), _T("error"), MB_OK);
closesocket(m_ServerSocket) ;
WSACleanup();
PostQuitMessage(0);
return;
}
nRet = listen(m_ServerSocket, 10); // 10 is the number of clients that can be queued
if (nRet == SOCKET_ERROR)
{
MessageBox(hWnd, _T ("listen error \n"), _T("error"), MB_OK);
WSACleanup();
return;
}
} |
En Natuurlijk de Client proc : (deze is niet async.)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| void ClientProc(PVOID pvoid)
{
PPARAMS parameters;
parameters = (PPARAMS)pvoid;
SOCKET clientSocket = parameters->socket;
TCHAR* pszTemp = new TCHAR[MAX_PATH];
fd_set fds_w, fds_r;
while (true)
{
memset(pszTemp, 0, sizeof(TCHAR) * MAX_PATH);
FD_ZERO(&fds_r);
FD_ZERO(&fds_w);
FD_SET(clientSocket,&fds_r);
FD_SET(clientSocket,&fds_w);
select(0, &fds_r, &fds_w, NULL, NULL);
int read = FD_ISSET(clientSocket, &fds_r);
int write = FD_ISSET(clientSocket, &fds_w);
if (read!=0)
{
ioctlsocket(clientSocket, FIONREAD, &ulSize);
recv(clientSocket, pszTemp, ulSize , MSG_PEEK);
//parameters->hWnd
MessageBox(NULL, pszTemp, _T("Incoming"), MB_OK);
}
}
delete[] pszTemp;
closesocket(clientSocket);
_endthread();
} |