Networking (WinSock)
Don Freeman

Ok...I am REALLY getting frustrated trying to figure this out!!! >:( I am trying to create a client/server system that will be used in an upcoming game. I am trying to get the FD_xx options to work correctly. Can someone please take a look at this and tell me what (if anything) I am doing wrong? ??? The problem I am getting now is when I run the server, then the client...The server picks up that the client has sent data. Good...it should. But when I go to READ that data...I get the WinSock error: 10014 - WSAEFAULT. The description from Microsoft's docs:
-------------------------------------------------------------------------------------
WSAFAULT (10014): Bad address.
The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error occurs if an application passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an argument which is a struct sockaddr is smaller than sizeof(struct sockaddr).
-------------------------------------------------------------------------------------
[EDIT]
Also: I sometimes get:
WSAECONNABORTED
(10053)
Software caused connection abort.
An established connection was aborted by the software in your host machine, possibly due to a data transmission timeout or protocol error.
-------------------------------------------------------------------------------------
The client was not disconnected...it was still running! Does this mean this is a firewall issue? It is just (well should be) running on the local machine, so I don't see why that would be an issue...::)
I am probably missing something somewhere...but my eyes can't see it right now...please...anyone help? ::)

#SelectExpand
1////////////////////////////////////////////////////////////////////////////////////////////////// 2// <Main.cpp> 3////////////////////////////////////////////////////////////////////////////////////////////////// 4#define ALLEGRO_USE_CONSOLE 5#include <allegro.h> 6#include <winalleg.h> 7////////////////////////////////////////////////////////////////////////////////////////////////// 8#include <winsock.h> 9#include <stdio.h> 10////////////////////////////////////////////////////////////////////////////////////////////////// 11#define BUFFERSIZE 255 12////////////////////////////////////////////////////////////////////////////////////////////////// 13int main( void ) 14{ 15 ////////////////////////////////////////////////////////////////////////////////////////////// 16 WORD wsVersionRequested = MAKEWORD(1,1); 17 USHORT iPort = 42479; 18 SOCKET sListenSocket = INVALID_SOCKET; 19 SOCKET sAcceptSocket = INVALID_SOCKET; 20 WSADATA wsaData; 21 FD_SET fdRead; 22 FD_SET fdWrite; 23 ULONG iNonBlocking = 1; 24 char iReuseAddress = 1; 25 DWORD dwFlags = 0; 26 SOCKADDR_IN sInternetAddress; 27 SOCKADDR_IN sRemoteAddress; 28 int iRemoteAddressLength = sizeof(sRemoteAddress); 29 ////////////////////////////////////////////////////////////////////////////////////////////// 30 // [Network startup] 31 printf("Server...\n"); 32 printf(" [Network]-><WSAStartup>->WinSock version(%i,%i)\n",LOBYTE(wsVersionRequested), 33 HIBYTE(wsVersionRequested)); 34 if ( WSAStartup(wsVersionRequested,&wsaData) != 0 ) 35 { 36 printf(" [Network]->Error!<WSAStartup>->%i\n",WSAGetLastError()); 37 printf(" [System]->Shutdown started...\n"); 38 printf(" [System]->Shut down.\n"); 39 printf("Goodbye! :)\n"); 40 return 1; 41 } 42 if ( LOBYTE(wsaData.wVersion) != LOBYTE(wsVersionRequested) || 43 HIBYTE(wsaData.wVersion) != HIBYTE(wsVersionRequested) ) 44 { 45 printf(" [Network]->Error!<WSAStartup>->Error setting requested version!\n"); 46 printf(" [System]->Shutdown started...\n"); 47 printf(" [Network]->Shutting down WinSock.\n"); 48 WSACleanup(); 49 printf(" [System]->Shut down.\n"); 50 printf("Goodbye! :)\n"); 51 return 1; 52 } 53 ////////////////////////////////////////////////////////////////////////////////////////////// 54 // [Create listening socket] 55 printf(" [Network]->Attempting to create listening socket...\n"); 56 sListenSocket = socket(PF_INET,SOCK_STREAM,0); 57 if ( sListenSocket == INVALID_SOCKET ) 58 { 59 printf(" [Network]->Error! Listening socket invalid!->%i\n",WSAGetLastError()); 60 printf(" [System]->Shutdown started...\n"); 61 printf(" [Network]->Shutting down WinSock.\n"); 62 WSACleanup(); 63 printf(" [System]->Shut down.\n"); 64 printf("Goodbye! :)\n"); 65 return 1; 66 } 67 ////////////////////////////////////////////////////////////////////////////////////////////// 68 // [Set listening socket address] 69 printf(" [Network]->Setting listening socket address fields."); 70 sInternetAddress.sin_family = AF_INET; 71 sInternetAddress.sin_addr.s_addr = htonl(INADDR_ANY); 72 sInternetAddress.sin_port = htons(iPort); 73 memset(sInternetAddress.sin_zero,'\0',8); 74 printf("Done.\n"); 75 ////////////////////////////////////////////////////////////////////////////////////////////// 76 // [Bind listening socket] 77 printf(" [Network]->Attempting to bind listening socket.\n"); 78 if ( bind(sListenSocket,(struct sockaddr*)&sInternetAddress, 79 sizeof(SOCKADDR_IN) ) != 0 ) 80 { 81 printf(" [Network]->Error binding listening socket!->%i\n",WSAGetLastError()); 82 printf(" [System]->Shutdown started...\n"); 83 printf(" [Network]->Closing listening socket.\n"); 84 closesocket(sListenSocket); 85 printf(" [Network]->Shutting down WinSock.\n"); 86 WSACleanup(); 87 printf(" [System]->Shut down.\n"); 88 printf("Goodbye! :)\n"); 89 return 1; 90 } 91 ////////////////////////////////////////////////////////////////////////////////////////////// 92 printf(" [Network]->Setting listening socket to NON-BLOCKING mode.\n"); 93 if( ioctlsocket(sListenSocket,FIONBIO,&iNonBlocking) == SOCKET_ERROR ) 94 { 95 printf(" [Network]->Error setting NON-BLOCKING mode!->%i\n",WSAGetLastError()); 96 printf(" [System]->Shutdown started...\n"); 97 printf(" [Network]->Closing listening socket.\n"); 98 closesocket(sListenSocket); 99 printf(" [Network]->Shutting down WinSock.\n"); 100 WSACleanup(); 101 printf(" [System]->Shut down.\n"); 102 printf("Goodbye! :)\n"); 103 return 1; 104 } 105 printf(" [Network]->Setting listening socket option->Reuse address mode.\n"); 106 //if( ioctlsocket(sListenSocket,SO_REUSEADDR,&iReuseAddress) == SOCKET_ERROR ) 107 if( setsockopt(sListenSocket,SOL_SOCKET, SO_REUSEADDR, &iReuseAddress, 108 sizeof(iReuseAddress)) == SOCKET_ERROR ) 109 { 110 printf(" [Network]->Error setting SO_REUSEADDR mode!->%i\n",WSAGetLastError()); 111 printf(" [System]->Shutdown started...\n"); 112 printf(" [Network]->Closing listening socket.\n"); 113 closesocket(sListenSocket); 114 printf(" [Network]->Shutting down WinSock.\n"); 115 WSACleanup(); 116 printf(" [System]->Shut down.\n"); 117 printf("Goodbye! :)\n"); 118 return 1; 119 } 120 ////////////////////////////////////////////////////////////////////////////////////////////// 121 printf(" [Network]->Attempt listen...\n"); 122 if ( listen(sListenSocket,5) == SOCKET_ERROR ) 123 { 124 printf(" [Network]->Error listening!->%i\n",WSAGetLastError()); 125 printf(" [System]->Shutdown started...\n"); 126 printf(" [Network]->Closing listening socket.\n"); 127 closesocket(sListenSocket); 128 printf(" [Network]->Shutting down WinSock.\n"); 129 WSACleanup(); 130 printf(" [System]->Shut down.\n"); 131 printf("Goodbye! :)\n"); 132 return 1; 133 } 134 ////////////////////////////////////////////////////////////////////////////////////////////// 135 printf(" [Allegro]->Initialize system.\n"); 136 allegro_init(); 137 printf(" [Allegro]->Setting color depth.\n"); 138 set_color_depth(32); 139 printf(" [Allegro]->Setting GFX mode.\n"); 140 set_gfx_mode(GFX_AUTODETECT_WINDOWED,400,400,0,0); 141 printf(" [Allegro]->Setting color conversion.\n"); 142 set_color_conversion(COLORCONV_TOTAL); 143 printf(" [Allegro]->Starting timer.\n"); 144 install_timer(); 145 printf(" [Allegro]->Starting keyboard service.\n"); 146 install_keyboard(); 147 printf(" [Allegro]->Starting mouse service.\n"); 148 install_mouse(); 149 ////////////////////////////////////////////////////////////////////////////////////////////// 150 printf(" [Allegro]->Setting color depth.\n"); 151 BITMAP *pBmp = create_bitmap(SCREEN_W,SCREEN_H); 152 if ( !pBmp ) 153 { 154 printf(" [Allegro]->Error creating buffer!\n"); 155 printf(" [System]->Shutdown started...\n"); 156 printf(" [Network]->Closing listening socket.\n"); 157 closesocket(sListenSocket); 158 printf(" [Network]->Shutting down WinSock.\n"); 159 WSACleanup(); 160 printf(" [System]->Shut down.\n"); 161 printf("Goodbye! :)\n"); 162 return 1; 163 } 164 clear_bitmap(pBmp); 165 ////////////////////////////////////////////////////////////////////////////////////////////// 166 printf(" [System]->Enter main loop.\n"); 167 // SOCKET accept( SOCKET s, struct sockaddr FAR* addr,int FAR* addrlen ); 168 while ( true ) 169 { 170 // [Network code] 171 FD_ZERO(&fdRead); 172 FD_ZERO(&fdWrite); 173 timeval tv = { 0, 0 }; 174 // check for connection attempts 175 sAcceptSocket = accept(sListenSocket,(struct sockaddr*)&sRemoteAddress, 176 &iRemoteAddressLength); 177 if ( sAcceptSocket == INVALID_SOCKET ) 178 { 179 int i = WSAGetLastError(); 180 if ( i == WSAEWOULDBLOCK ) 181 { 182 //printf(" [Network]->Accept->Waiting for connections...\n"); 183 } 184 else 185 { 186 printf(" [Network]->Accept->Error!->%i\n",i); 187 break; 188 } 189 } 190 else 191 { 192 FD_SET(sAcceptSocket,&fdRead); 193 FD_SET(sAcceptSocket,&fdWrite); 194 if ( select(0,&fdRead,&fdWrite,NULL,&tv ) == SOCKET_ERROR ) 195 { 196 printf(" [Network]->Select error!->%i\n",WSAGetLastError()); 197 } 198 else 199 { 200 printf(" [Network]->Select->OK.\n"); 201 } 202 if ( FD_ISSET(sAcceptSocket,&fdRead) ) 203 { 204 printf( " [Network]-><Remote>->Ready to receive data...\n"); 205 } 206 if ( FD_ISSET(sAcceptSocket,&fdWrite) ) 207 { 208 printf( " [Network]-><Remote>->Ready to send data...\n"); 209 char *cBuffer = NULL; 210 DWORD dwTotalBytesReceived = recv(sAcceptSocket,cBuffer,BUFFERSIZE,0); 211 if ( dwTotalBytesReceived == SOCKET_ERROR ) 212 { 213 printf(" [Network]->Error receiving data!->%i\n",WSAGetLastError()); 214 } 215 else 216 { 217 printf(" [Network]-><Remote>->TotalSent->%i\n",dwTotalBytesReceived); 218 if ( dwTotalBytesReceived > 0 ) 219 { 220 printf(" [Network]-><Remote>->[Message]->%s\n",cBuffer); 221 } 222 } 223 } 224 //FD_CLR(sAcceptSocket,&fdRead); 225 //FD_CLR(sAcceptSocket,&fdWrite); 226 } 227 closesocket(sAcceptSocket); 228 // [Allegro code] 229 if ( keypressed() ) 230 { 231 if ( key[KEY_ESC] ) 232 { 233 clear_keybuf(); 234 break; 235 } 236 } 237 clear_bitmap(pBmp); 238 textprintf(pBmp,font,0,SCREEN_H-text_height(font),makecol(255,255,255), 239 "Press ESC key to exit..."); 240 blit(pBmp,screen,0,0,0,0,pBmp->w,pBmp->h); 241 } 242 printf(" [System]->Leaving main loop.\n"); 243 ////////////////////////////////////////////////////////////////////////////////////////////// 244 // [Cleanup] 245 printf(" [System]->Shutdown started...\n"); 246 printf(" [Allegro]->Cleanup objects.\n"); 247 destroy_bitmap(pBmp); 248 pBmp = NULL; 249 printf(" [Network]->Closing listening socket.\n"); 250 closesocket(sListenSocket); 251 printf(" [Network]->Closing remote socket.\n"); 252 closesocket(sAcceptSocket); 253 printf(" [Network]->Shutting down WinSock.\n"); 254 WSACleanup(); 255 printf(" [System]->Shut down.\n"); 256 printf("Goodbye! :)\n"); 257 ////////////////////////////////////////////////////////////////////////////////////////////// 258 return 0; 259 ////////////////////////////////////////////////////////////////////////////////////////////// 260} 261END_OF_MAIN() 262//////////////////////////////////////////////////////////////////////////////////////////////////

Sorry for the long code...the actual working code is not that much...it is mainly all the verbose error checking code I put in...

The client binary is attached....(win32)
or clicky:
http://64.246.37.217/files/attachment/590432

The compiled server binary is attached also...(win32)
or clicky:
http://64.246.37.217/files/attachment/590433

Thanks in advance,
Donald 8-)

ReyBrujo

You use select to check whether you need to accept a new connection, or receive data. You are accepting when there is no need to do that. The code is complex because you did not do it in the standard way, were you using select to multiplex the information from the socket, it would be easier :(

Don Freeman

Basically what you are saying is that I should use something like this:

1[MAIN LOOP]
2 select(...)
3 if ( select tells me pending connection )
4 {
5 accept(...)
6 if ( accepted sock valid )
7 {
8 process accepted socket
9 }
10 else
11 {
12 socket was invalid
13 }
14 }
15 do other stuff
16[/MAIN LOOP]

Pseudo code (of course)...::)

Only question:
How do I know when select will return the connection attempt? ???

Thanks for your quick response,
Donald

ReyBrujo

Yes. I will tell you to check this again. When the connection is attempted, FD_ISSET will return true when you check the socket where you are listening. If FD_ISSET returns true in a socket that has already been accepted, then you are going to receive information.

    /*  check if the descriptor set is our listening one  */
    if (FD_ISSET(descriptor , &input)) {
        sockets[sockets_index] = accept(descriptor, NULL, NULL);
        /*  more code about accepting  */
    }
    /*  one of the sockets is sending data. Find it  */
    else {
        /*  receive information from a socket  */
    }

Note that descriptor is the socket at which you did listen.

Don Freeman

Ok...Thanks man! It just gets frustrating after awhile...I didn't want to ask for help, but it looks like I needed to anyway... :(

The FD_xx is what was confusing for me... My docs are kind of hard to follow about how to use them correctly...

Thanks again,
Donald

Thread #588389. Printed from Allegro.cc