Skip to main content
gamedev.net
🔒 Locked

receive()

Started by GravtyKlz 12 replies 900+ views
Original Post
GravtyKlz
GravtyKlz
When you call listen does it constantly listen or just for that second when you call it. When I call listen( ) it listens for that moment but then goes on to the next line of code.
if (listen(ListeningSocket, 5) == SOCKET_ERROR)
{
   printf("listen failed with error %d\n", WSAGetLastError());
   closesocket(ListeningSocket);
   WSACleanup();
   return;
} 

// This is the part that fails and gives an error
if ((NewConnection = accept(ListeningSocket, (SOCKADDR *) &ClientAddr, &ClientAddrLen)) == INVALID_SOCKET)
{
   printf("accept failed with error %d\n", WSAGetLastError());
   closesocket(ListeningSocket);
   WSACleanup();
   return;
}
  
[edited by - gravtyklz on March 12, 2003 2:26:47 PM]
GravtyKlz
GravtyKlz
I was just reading some other posts on here and someone mentioned that accept() is like getchar() in that it waits until there is a connection. My program doesnt do that. It immediately attempts and shows the error.
niyaw
niyaw
the docs are pretty clear on what listen does.
GravtyKlz
GravtyKlz
I read the docs for accept but Im still not sure about that.
x33
x33
Do you check for errors in the socket() function? You should check it and then post the retval of all three functions here. It would be much easier to help you if we had more info. As for the listen() you must think of as if it was creating a queue for incoming connection requests. It doesn''t block and it doesn''t perform the listening itself. Accept() does. Listen() creates the queue and then your app continues. And when you call the accept() it checks if there is a connection request in the listen queue and if there is it accepts the connection (on client side the connect() returns success). If there''s no connection request in the queue it waits until there is. Accept blocks your app and only returns success when the connection between client and server is established. It returns a socket descriptor which is later used to transfer data between client and server.

"I''ll be Bach!" (c) Johann Sebastian Schwarzenegger
"I'll be Bach!" (c) Johann Sebastian Schwarzenegger
no1spec
no1spec
One thing to look at is if the socket is set to non-blocking. If this is the case accept will just return.
GravtyKlz
GravtyKlz
I''m using example source from a book. I know sort of what blocking, non-blocking and I think for what I want is blocking, but I dont see anywhere in the code where it would specify which to use.


void main(void)
{
WSADATA wsaData;
SOCKET ListeningSocket;
SOCKET NewConnection;
SOCKADDR_IN ServerAddr;
SOCKADDR_IN ClientAddr;
int ClientAddrLen;
int Port = 5150;
int Ret;
char DataBuffer[1024];

// Initialize Winsock version 2.2

if ((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)
{
// NOTE: Since Winsock failed to load we cannot use WSAGetLastError
// to determine the error code as is normally done when a Winsock
// API fails. We have to report the return status of the function.

printf("WSAStartup failed with error %d\n", Ret);
return;
}

// Create a new socket to listening for client connections.

if ((ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))
== INVALID_SOCKET)
{
printf("socket failed with error %d\n", WSAGetLastError());
WSACleanup();
return;
}

// Setup a SOCKADDR_IN structure that will tell bind that we
// want to listen for connections on all interfaces using port
// 5150. Notice how we convert the Port variable from host byte
// order to network byte order.

ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(Port);
ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);

// Associate the address information with the socket using bind.

if (bind(ListeningSocket, (SOCKADDR *)&ServerAddr, sizeof(ServerAddr))
== SOCKET_ERROR)
{
printf("bind failed with error %d\n", WSAGetLastError());
closesocket(ListeningSocket);
WSACleanup();
return;
}

// Listen for client connections. We used a backlog of 5 which is
// normal for many applications.

if (listen(ListeningSocket, 5) == SOCKET_ERROR)
{
printf("listen failed with error %d\n", WSAGetLastError());
closesocket(ListeningSocket);
WSACleanup();
return;
}

printf("We are awaiting a connection on port %d.\n", Port);

// Accept a new connection when one arrives.

if ((NewConnection = accept(ListeningSocket, (SOCKADDR *) &ClientAddr,
&ClientAddrLen)) == INVALID_SOCKET)
{
printf("accept failed with error %d\n", WSAGetLastError());
closesocket(ListeningSocket);
WSACleanup();
return;
}


printf("We successfully got a connection from %s:%d.\n",
inet_ntoa(ClientAddr.sin_addr), ntohs(ClientAddr.sin_port));

// At this point you can do two things with these sockets. Await
// for more connections by calling accept again on ListeningSocket
// and start sending or receiving data on NewConnection. For
// simplicity We will stop listening for more connections by closing
// ListeningSocket. We will start sending and receiving data on
// NewConnection.

closesocket(ListeningSocket);

// Start sending and receiving data on NewConnection. For simplicity,
// we will just receive some data and report how many bytes were
// received.

printf("We are waiting to receive data...\n");

if ((Ret = recv(NewConnection, DataBuffer, sizeof(DataBuffer), 0))
== SOCKET_ERROR)
{
printf("recv failed with error %d\n", WSAGetLastError());
closesocket(NewConnection);
WSACleanup();
return;
}

printf("We successfully received %d byte(s).\n", Ret);

// For this application we do not plan to do anything else with the
// connection so we will just close the connection.

printf("We are now going to close the client connection.\n");

closesocket(NewConnection);

// When your application is finished handling the connections
// call WSACleanup.

WSACleanup();
}
no1spec
no1spec
Usually you have to specifically turn on non-blocking so that probably isn''t it.

What is the output of the program when you run it? Primarily from printf("accept failed with error %d\n", WSAGetLastError());

x33
x33
#1 - The 3rd parameter for socket() should be zero when used with SOCK_STREAM ('socket(PF_INET, SOCK_STREAM, 0);'). And IPPROTO_TCP is defined as '6' in winsock2.h. IPPROTO_TCP is for use with SOCK_RAW. Put a zero instead if IPPROTO_TCP. By the way, use PF_INET instead of AF_INET. PF_ is 'protocol family' and AF_ is 'address family'. Nowadays these constants are interchangeable but in future the situation can change.
#2 - Don't do htonl on INADDR_ANY. Simply do a 'ServerAddr.sin_addr.s_addr = INADDR_ANY;'.

If you still have problems just paste you app's output, and i'll try to help.


"I'll be Bach!" (c) Johann Sebastian Schwarzenegger

[edited by - x33 on March 12, 2003 10:48:10 PM]
"I'll be Bach!" (c) Johann Sebastian Schwarzenegger
GravtyKlz
GravtyKlz
I made all the changes suggested...it still stops at accept.

printf("accept failed with error %d\n", WSAGetLastError());

Thats what it prints out with the error being "10014"

Im guessing this is blocking, which calls accept once and goes on with it. And Im assuming I need to make it non-blocking which waits at accept() until there is a connection. Am I right on this?
no1spec
no1spec
Try adding the following:

ClientAddrLen = sizeof(ClientAddr);

before the accept call.
x33
x33
You can accept() with ServerAddr passed as the 2nd parameter. That''s it. You don''t need to have another address struct (i mean ClientAddr). Your app can only communicate with one client at a time. And it is 100% blocking. You don''t have to worry about blocking and non-blocking. By the way, the 2nd and the 3rd parameters of the accept() are not obligatory.

"I''ll be Bach!" (c) Johann Sebastian Schwarzenegger
"I'll be Bach!" (c) Johann Sebastian Schwarzenegger
GravtyKlz
GravtyKlz
ClientAddrLen = sizeof(ClientAddr);

That fixed the problem. I dont know why the book I have didnt include that. If I would have stopped and looked at the code more instead of thinking I was missing a call or argument somewhere I may have been able to find it. Thanks a lot guys.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.