Unable to bind a 2nd time if recv receives all bytes sent


A

Andre

Hi All,

I have written these very simple server and client, but the server
always crashes at the 2nd loop when it tries to bind again, and issues
an "Address already in use" error message.

But if I change

"if(recv(remoteSocketFd,(void *)
&messageToReceive,messageToReceiveLength,0) < 0)"

to

"if(recv(remoteSocketFd,(void *)
&messageToReceive,messageToReceiveLength - 1,0) < 0)"

the server is able to bind again in every single loop, but off course
it doesn't receive the correct value sent by the client.

How can this issue be corrected?

Thanks in advance,

Andre

// server

#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>

#define CONNECTION_QUEUE_SIZE 5

#define SUCCESSED 1
#define ERROR 0

#define PORT 4000
#define HOST "127.0.0.1"


int main(int argc, char * argv[])
{
unsigned int messageToReceive;
int messageToReceiveLength;
int localSocketFd;
int remoteSocketFd;
struct sockaddr_in targetAddress;
struct sockaddr_in localServerAddress;
struct sockaddr_in remoteClientAddress;
int remoteClientAddressLength;

while(1)
{
remoteClientAddressLength = sizeof(struct sockaddr_in);

localSocketFd = socket(AF_INET, SOCK_STREAM, 0);
if(localSocketFd < 0)
{
return ERROR;
}

memset((void *)&localServerAddress, 0, sizeof(struct
sockaddr_in));
localServerAddress.sin_family = AF_INET;
localServerAddress.sin_port = htons(PORT);
localServerAddress.sin_addr.s_addr = INADDR_ANY;

if(bind(localSocketFd,
(struct sockaddr *)&localServerAddress,
sizeof(localServerAddress)) < 0)
{
printf("%s\n", strerror(errno));
return ERROR;
}

if(listen(localSocketFd, CONNECTION_QUEUE_SIZE))
{
return ERROR;
}

remoteSocketFd = accept(localSocketFd,
(struct sockaddr *)&remoteClientAddress,
(socklen_t*)&remoteClientAddressLength);
if(remoteSocketFd < 0)
{
return ERROR;
}

messageToReceiveLength = sizeof(messageToReceive);
if(recv(remoteSocketFd,
(void *)&messageToReceive,
messageToReceiveLength,
0) < 0)
{
return ERROR;
}

if(localSocketFd != -1)
{
if(close(localSocketFd) != 0)
{
return ERROR;
}
}

if(remoteSocketFd != -1)
{
if(close(remoteSocketFd) != 0)
{
return ERROR;
}
}
}

return SUCCESSED;
}

// client

#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>

#define CONNECTION_QUEUE_SIZE 5

#define SUCCESSED 1
#define ERROR 0

#define PORT 4000
#define HOST "127.0.0.1"

#define NUMBER 10


int main(int argc, char * argv[])
{
struct hostent * hostAddress;
struct sockaddr_in targetAddress;
int localSocketFd;
int remoteSocketFd;
unsigned int messageToSend = htonl(NUMBER);

while(1)
{
remoteSocketFd = socket(AF_INET, SOCK_STREAM, 0);
if(remoteSocketFd < 0)
{
return ERROR;
}

hostAddress = gethostbyname(HOST);
if(!hostAddress)
{
return ERROR;
}

memset((void *)&targetAddress, 0, sizeof(struct sockaddr_in));
targetAddress.sin_family = AF_INET;
targetAddress.sin_port = htons(PORT);
memcpy((void *)&targetAddress.sin_addr.s_addr,
(void *)hostAddress->h_addr,
hostAddress->h_length);

if(connect(remoteSocketFd,
(struct sockaddr *)&targetAddress,
sizeof(struct sockaddr)) == -1)
{
printf("1\n");
return ERROR;
}

if(send(remoteSocketFd,
(void *)&messageToSend,
sizeof(messageToSend),
0) < 0)
{
printf("2\n");
return ERROR;
}

if(remoteSocketFd != -1)
{
if(close(remoteSocketFd) != 0)
{
printf("3\n");
return ERROR;
}
}
}

return SUCCESSED;
}
 
Ad

Advertisements

I

Ian Collins

Andre said:
Hi All,

I have written these very simple server and client, but the server
always crashes at the 2nd loop when it tries to bind again, and issues
an "Address already in use" error message.
You're well OT here, try comp.unix.programmer.
 
M

Martien Verbruggen

Hi All,

I have written these very simple server and client, but the server
always crashes at the 2nd loop when it tries to bind again, and issues
an "Address already in use" error message.

If you need future help with this sort of code, you should post in
comp.unix.programmer, which is where the people who know about the Unix
sockets API hang out.

Check out setsockopt() and SO_REUSEADDR.

Martien
 
R

Richard Tobin

Andre said:
I have written these very simple server and client, but the server
always crashes at the 2nd loop when it tries to bind again, and issues
an "Address already in use" error message.

You bind(), listen(), accept(), and that gives you a new socket to
recv() (or whatever) on. You don't need to keep rebinding the
original socket; it's just the accept() that you want to repeat. Take
the bind() and listen() out of the loop.

If you want to go into this in more detail, a unix newsgroup would
be more appropriate.

-- Richard
 
R

Richard Tobin

Check out setsockopt() and SO_REUSEADDR.

That's not the problem here. The problem is the unnecessary creation
of multiple passive sockets listening on the same port.

-- Richard
 
A

Andre

Sorry for posting an out of topic message here, and thanks for all
suggestions.

But just in case someone run into the same error, and come across this
message in the future, this is the modified server code that fixes
this problem.

Andre

#define CONNECTION_QUEUE_SIZE 5

#define SUCCESSED 1
#define ERROR 0

#define PORT 4000
#define HOST "127.0.0.1"


int main(int argc, char * argv[])
{
unsigned int number = 0;

unsigned int messageToReceive;
int messageToReceiveLength;
int localSocketFd;
int remoteSocketFd;
struct sockaddr_in targetAddress;
struct sockaddr_in localServerAddress;
struct sockaddr_in remoteClientAddress;
int remoteClientAddressLength;

localSocketFd = socket(AF_INET, SOCK_STREAM, 0);
if(localSocketFd < 0)
{
return ERROR;
}

memset((void *)&localServerAddress, 0, sizeof(struct sockaddr_in));
localServerAddress.sin_family = AF_INET;
localServerAddress.sin_port = htons(PORT);
localServerAddress.sin_addr.s_addr = INADDR_ANY;

if(bind(localSocketFd,
(struct sockaddr *)&localServerAddress,
sizeof(localServerAddress)) < 0)
{
printf("%s\n", strerror(errno));
return ERROR;
}

if(listen(localSocketFd, CONNECTION_QUEUE_SIZE))
{
return ERROR;
}

while(1)
{
printf("%d\n", number++);

remoteClientAddressLength = sizeof(struct sockaddr_in);

remoteSocketFd = accept(localSocketFd,
(struct sockaddr *)&remoteClientAddress,
(socklen_t*)&remoteClientAddressLength);
if(remoteSocketFd < 0)
{
return ERROR;
}

messageToReceiveLength = sizeof(messageToReceive);
if(recv(remoteSocketFd,
(void *)&messageToReceive,
messageToReceiveLength,
0) < 0)
{
return ERROR;
}

if(remoteSocketFd != -1)
{
if(close(remoteSocketFd) != 0)
{
return ERROR;
}
}
}

if(localSocketFd != -1)
{
if(close(localSocketFd) != 0)
{
return ERROR;
}
}

return SUCCESSED;
}
 
Ad

Advertisements

M

Martien Verbruggen

That's not the problem here. The problem is the unnecessary creation
of multiple passive sockets listening on the same port.

That'll teach me to read the code submitted a bit better, rather than to
assume that the problem is the same as it almost always is when people
complain about not being able to bind a second time.

Excuses to the OP.

Martien
 
C

CBFalconer

Martien said:
That'll teach me to read the code submitted a bit better, rather
than to assume that the problem is the same as it almost always
is when people complain about not being able to bind a second
time.

No, that simply reinforces the advice to advise where to ask,
rather than give an off-topic answer. You did both.
 
A

Antoninus Twink

No, that simply reinforces the advice to advise where to ask,
rather than give an off-topic answer. You did both.

Idiot.

It does exactly the opposite.

The argument that the topicality taliban always trot out is "post
somewhere else so that errors will be seen and corrected by experts".

He posted here. An expert (Richard Tobin) saw and corrected his error.

There are enough *nix experts who read clc that there will ALWAYS be an
expert to spot EVERY error. Therefore the zealots' argument is complete
hokum.
 
S

Stephen Sprunk

Andre said:
Hi All,

I have written these very simple server and client, but the server
always crashes at the 2nd loop when it tries to bind again, and issues
an "Address already in use" error message.

Sockets are off-topic for comp.lang.c; since you appear to be using a
POSIX system, try comp.unix.programmer.

<OT>
However, I think I know what your problem is (actually, several), so
I'll take a stab at it:
while(1)
{
remoteClientAddressLength = sizeof(struct sockaddr_in);

localSocketFd = socket(AF_INET, SOCK_STREAM, 0);
if(localSocketFd < 0)
{
return ERROR;
}

memset((void *)&localServerAddress, 0, sizeof(struct
sockaddr_in));
localServerAddress.sin_family = AF_INET;
localServerAddress.sin_port = htons(PORT);
localServerAddress.sin_addr.s_addr = INADDR_ANY;

if(bind(localSocketFd,
(struct sockaddr *)&localServerAddress,
sizeof(localServerAddress)) < 0)
{
printf("%s\n", strerror(errno));
return ERROR;
}

if(listen(localSocketFd, CONNECTION_QUEUE_SIZE))
{
return ERROR;
}

Your bind() and listen() calls should be _before_ the loop, not inside
it. You only need one listening socket for multiple inbound connections.
remoteSocketFd = accept(localSocketFd,
(struct sockaddr *)&remoteClientAddress,
(socklen_t*)&remoteClientAddressLength);
if(remoteSocketFd < 0)
{
return ERROR;
}

messageToReceiveLength = sizeof(messageToReceive);
if(recv(remoteSocketFd,
(void *)&messageToReceive,
messageToReceiveLength,
0) < 0)
{
return ERROR;
}

if(localSocketFd != -1)

localSocketFd hasn't been modified since the original socket() call, and
your code would have returned (above) if it were not positive, so this
"if" will _always_ be true.
{
if(close(localSocketFd) != 0)
{
return ERROR;
}
}

Don't close the listening socket until the loop is finished. Constantly
closing and opening listening sockets will cause you several different
problems.

if(remoteSocketFd != -1)
{
if(close(remoteSocketFd) != 0)
{
return ERROR;
}
}
}

return SUCCESSED;

How do you expect your code to reach this? There is no "break" in your
while(1) loop. And, while I hate to pick nits, "successed" is not a
word; EXIT_SUCCESS and EXIT_FAIL (defined in <stdlib.h>) are better
choices for values to return from main().

S
 
C

CBFalconer

Stephen said:
Sockets are off-topic for comp.lang.c; since you appear to be using
a POSIX system, try comp.unix.programmer.

<OT>
However, I think I know what your problem is (actually, several),
so I'll take a stab at it:

If you do that, I suggest you cross-post to comp.unix.programmer,
and also set follow-ups to there. That way your answer has a
reasonable chance of receiving proper criticism, and you are not
extending the off-topic thread here.
 
Ad

Advertisements

J

Joachim Schmitz

CBFalconer said:
If you do that, I suggest you cross-post to comp.unix.programmer,
and also set follow-ups to there. That way your answer has a
reasonable chance of receiving proper criticism,

Which doesn't realy work, if he doesn't read comp.unix.programmer.
and you are not
extending the off-topic thread here.

Bye, Jojo
 
J

James Kuyper

Joachim said:
CBFalconer wrote: ....

Which doesn't realy work, if he doesn't read comp.unix.programmer.

Well, obviously. The complete advice is that he must cross-post to
comp.unix.programmer, and THEN read comp.unix.programmer looking for the
answers, but the second part is normally considered to be implied by the
first part. Does the second part really need to be spelled out? If I
were to suggest to someone that they should ask their teacher about
something, is it really necessary for me to also specify that they
should stick around and listen to whatever answer the teacher might provide?
 
Ad

Advertisements

C

CBFalconer

Joachim said:
CBFalconer wrote:
.... snip ...


Which doesn't realy work, if he doesn't read comp.unix.programmer.

It doesn't take much effort on any reasonably modern newsreader, to
add a group to the reading list. Nor to take it out again when
done.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top