Connecting to Non-Blocking Server
I was going through the little tutorial on Non-blocking servers after toying with my own and while everything seems to be okay server side when I try to write just a basic connection function/program I always get a 10061 error - Host Connection refused.
I have heard with non-blocking servers you need to do some extra work on the send/recv functions just because of the loop that non-blocking servers use to check for incoming connections.
Is there anything in particular that is needed for a connection to a non-blocking server?
Here is my connect function, see anything wrong with it?
int main(void){ WORD Version; WSADATA wsadata; int nret = 0; char buffer[20]; char *hostname; Version = MAKEWORD(2,2); WSAStartup(Version, &wsadata); con << "Enter IP address: "; cin.getline(buffer,20); hostname = new char; strcpy(hostname,buffer); con << "Hostname OK!\n"; LPHOSTENT host; host = gethostbyname(hostname); if (!host) { con << Red << "Error getting host by name!\n" << Def; WSACleanup(); return -1; } SOCKET socketinfo = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if ( socketinfo == INVALID_SOCKET) { con << Red << "Error getting socket!\n" << Def; WSACleanup(); return -1; } SOCKADDR_IN server; server.sin_family = AF_INET; server.sin_addr = *((LPIN_ADDR)*host->h_addr_list); server.sin_port = htons(3636); if(FAILED(nret = connect(socketinfo, (LPSOCKADDR) &server, sizeof sockaddr))) { nret = WSAGetLastError(); con << "Connect failed! Nret - " << nret << "\n"; }
I don''t know if this is the problem, but you aren''t using gethostbyname() correctly. The contents of the hostent structure pointed to by the return value of gethostbyname() should be copied before any other Windows Sockets call is made. Possibly the call to socket() is clobbering the value, so you aren''t passing a good address to connect().
Okay, I''m dead stuck on this, here is the non-blocking functions I''m using.
and then main just calls CheckConnection in a loop so it constantly checks for any incoming connections on the port.
void ConnectionCheck(){ int store; int nfds; fd_set conn; int client_length = sizeof(Clients->clnt_addr); timeout.tv_sec = 0; timeout.tv_usec = 0; if(totalClients < MAX_PLAYERS) { FD_ZERO(&conn); FD_SET(listening,&conn); nfds = listening + 1; store = select(nfds,&conn, NULL, NULL, &timeout); if ( store > 0) { for (int check = 0; check < MAX_PLAYERS; check++) { if(Clients[check].busy == false) { Clients[check].Client = accept(listening, (struct sockaddr *)&Clients[check].clnt_addr, &client_length); char *ip = inet_ntoa(Clients[totalClients].clnt_addr.sin_addr); con << "IP : " << Red << ip << Def << " connected!\n"; totalClients++; Clients[check].busy = 1; break; } } } }}void ServerStart(){ WSADATA wsadata; server_addr.sin_family = AF_INET; server_addr.sin_port = htonl(PORT); //Port 3636 server_addr.sin_addr.s_addr = INADDR_ANY; WSAStartup(MAKEWORD(2,2),&wsadata); listening = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP); bind(listening,(struct sockaddr *)&server_addr,sizeof(server_addr)); listen(listening,SOMAXCONN); for (int i = 0; i < MAX_PLAYERS; i++) { Clients.busy = 0; };}
and then main just calls CheckConnection in a loop so it constantly checks for any incoming connections on the port.
I'm guessing the problem is with this line:
Try htons() instead of htonl() and see if it works.
As it is, you're taking 3636 as a host 32 bit int turning it into 3636 as a network 32 bit int, which is 0x340E0000 on the host architecture, then assigning it to a short. Which would just take the lower 16 bits, 0. This means you're binding on a random port instead of the specified port. So I'm guessing the reason you're client isn't connecting is because there's no socket listening on port 3636.
edit: and by the way, using [ source ] instead of
server_addr.sin_port = htonl(PORT); //Port 3636
Try htons() instead of htonl() and see if it works.
As it is, you're taking 3636 as a host 32 bit int turning it into 3636 as a network 32 bit int, which is 0x340E0000 on the host architecture, then assigning it to a short. Which would just take the lower 16 bits, 0. This means you're binding on a random port instead of the specified port. So I'm guessing the reason you're client isn't connecting is because there's no socket listening on port 3636.
edit: and by the way, using [ source ] instead of
for that above post might give slightly easier browsing. <br><br><SPAN CLASS=editedby>[edited by - SiCrane on December 12, 2003 12:22:37 AM]</SPAN>
*bangs head on wall*
Thanks, I figured it was something small like that. Now I just have to add a small loop to my connection function that will allow it to retry to connect if it happens to try and connect while the checkconnection function is not being called.
I assume that send and recv are basically the same with a non-blocking server as they are with a regular server but with alittle error checking since you have to make sure it gets the message when the message check function is called?
BTW SiCrane I really appreciate the help, I only hope I can be as helpful to someone in the future.
Thanks, I figured it was something small like that. Now I just have to add a small loop to my connection function that will allow it to retry to connect if it happens to try and connect while the checkconnection function is not being called.
I assume that send and recv are basically the same with a non-blocking server as they are with a regular server but with alittle error checking since you have to make sure it gets the message when the message check function is called?
BTW SiCrane I really appreciate the help, I only hope I can be as helpful to someone in the future.
Your welcome ![](smile.gif)
Anyways, you shouldn''t need a loop for the connection function. If the client is using blocking sockets, connect() will just block until it succeeds or encounters connection refused, etc. If the client is using non-blocking sockets, connect() should never return a successful result, instead giving a WSAEWOULDBLOCK result. You should then use select() to wait until actual connection is completed (which may be succesful or non-successful -- either way, FD_CONNECT is passed).
Using send() on non-blocking sockets is pretty much the same, though it seems to be more common with non-blocking sockets on TCP/IP that the entire buffer will not be sent in a single call. Also, two successive calls to send() may not complete happily, with the second one returning WSAEWOULDBLOCK. In which case, you''d have to use select() to find out when it''s safe to send() on that socket again.
Using recv(), in my experience, tends to be fairly similar between blocking and non-blocking sockets.
![](smile.gif)
Anyways, you shouldn''t need a loop for the connection function. If the client is using blocking sockets, connect() will just block until it succeeds or encounters connection refused, etc. If the client is using non-blocking sockets, connect() should never return a successful result, instead giving a WSAEWOULDBLOCK result. You should then use select() to wait until actual connection is completed (which may be succesful or non-successful -- either way, FD_CONNECT is passed).
Using send() on non-blocking sockets is pretty much the same, though it seems to be more common with non-blocking sockets on TCP/IP that the entire buffer will not be sent in a single call. Also, two successive calls to send() may not complete happily, with the second one returning WSAEWOULDBLOCK. In which case, you''d have to use select() to find out when it''s safe to send() on that socket again.
Using recv(), in my experience, tends to be fairly similar between blocking and non-blocking sockets.
I''m surprised nobody pointed this buffer overflow out
cin.getline(buffer,20);
hostname = new char;
strcpy(hostname,buffer);
buffer is 20 characters but you make hostname only 1 character in length. Then when you do strcpy its going to use 19 bytes that werent allocated. It may not cause problems now but when you start doing more memory allocation it will probably cause memory leaks.
it should be
hostname=new char[20];
just thought I would point that out
Clippy:"OMG, A NUMBAR! Let me format it for you"
Unsuspecting Student: "Ahhhhh! Damn you paperclip you ruined my paper. A thousand deaths upon you!"
"Game Programming: Without programming you''ve just got game"
cin.getline(buffer,20);
hostname = new char;
strcpy(hostname,buffer);
buffer is 20 characters but you make hostname only 1 character in length. Then when you do strcpy its going to use 19 bytes that werent allocated. It may not cause problems now but when you start doing more memory allocation it will probably cause memory leaks.
it should be
hostname=new char[20];
just thought I would point that out
Clippy:"OMG, A NUMBAR! Let me format it for you"
Unsuspecting Student: "Ahhhhh! Damn you paperclip you ruined my paper. A thousand deaths upon you!"
"Game Programming: Without programming you''ve just got game"
"Pfft, Facts! Facts can be used to prove anything!" -- Homer J. Simpson
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement