|
Networking (WinSock) |
Don Freeman
Member #5,110
October 2004
|
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: 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) The compiled server binary is attached also...(win32) Thanks in advance, -- |
ReyBrujo
Moderator
January 2001
|
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
Member #5,110
October 2004
|
Basically what you are saying is that I should use something like this: Pseudo code (of course)...::) Only question: Thanks for your quick response, -- |
ReyBrujo
Moderator
January 2001
|
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
Member #5,110
October 2004
|
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, -- |
|