Network port release?

hi

I have QNX 6 and have met a problem of network port release. I notice that after I close a socket, the port is not released. (If I run the same program, the system reports “Address already in use”). I have to wait for about one minute. The same code works fine under linux. Any idea how to fix this problem?

Thanks!

yyd_iris

yyd_iris,

That’s the IP stack holding the address/port for about 1 minute before letting it be reclaimed.

Try doing a setsockopt() with SO_REUSEADDR after creating your socket.

You can see all the options by looking at getsockopt in the helpviewer.

Tim

Thank you very much Tim! I try it and it works.

I have another question. My network server code cannot accept incoming socket. Again, the same pieces of codes works under linux.
Here are the codes:

    // skip the codes create listening_socket

socklen_t len;
SOCKET_HANDLE accepted_socket;
char errorInfo[1024];
accepted_socket = new SOCKET_HANDLE_STRUCT;
    len=sizeof(struct sockaddr_in);
accepted_socket->id=(SOCKET_DESC)accept(listening_socket->id,(struct sockaddr*)(&(listening_socket->saServer)),&len);
    // *** the accept function never returns ***/ 

Any idea?
Thanks!

yyd_iris

yyd_iris,

I assume you remembered to ‘bind’ to the listening socket before you did the listen() and accept() call like in this example:

beej.us/guide/bgnet/output/html/ … mpleserver

Assuming you have done that, are you sure your client machine is connecting to the server machine’s IP address on the right port?

What I would do is install tcpdump on the server machine from the 3rd party CD and run tcpdump and check to see if the client machine is actually connecting to your server machine.

There is no reason I know of that accept() wouldn’t return (the sample code I linked to above works for me) unless there is never an incoming client connection. Does your server work even one time or does it never work?

One thing to note. I think the first 1024 ports are privileged which means they are meant for root only access just in case your trying to use those ports as a non-root user.

Tim

Hi Tim,

I do bind() and listen() before calling accept().
The QNX machine (server) has IP:port 192.168.128.200:1173 (>1024) and I have root priority. The client is a linux machine and has IP:port 192.168.128.199:1172.
I install tcpdump and paste its result at the end of this message.
Any hint?

Thanks!
yyd_iris

tcpdump: listening on eth0

19:35:50.000031 192.168.128.200.65526 > 192.168.128.199.1172: S 1265284287:1265284287(0) win 16384 <mss 1460,nop,wscale 0,nop,nop,timestamp 0 0>
19:35:50.000031 192.168.128.199.1172 > 192.168.128.200.65526: R 0:0(0) ack 1265284288 win 0 (DF)
19:35:50.000033 192.168.128.200.65516 > primo.cs.umass.edu.domain: 18635+ AXFR (Class 53783)? 199.128.168.192.in-ad^@^@. (46)
19:35:50.000043 primo.cs.umass.edu.domain > 192.168.128.200.65516: 18635 NXDomain* 0/1/0 (123) (DF)
19:35:50.000045 192.168.128.200.65515 > primo.cs.umass.edu.domain: 18636+ AXFR (Class 53783)? 200.128.168.192.in-ad^@^@. (46)
19:35:50.000046 primo.cs.umass.edu.domain > 192.168.128.200.65515: 18636 NXDomain* 0/1/0 (123) (DF)
19:35:50.000048 192.168.128.200.65514 > primo.cs.umass.edu.domain: 18637+ Type0 (Class 252)? 1.240.119.128.in-addr. (44)
19:35:50.000053 primo.cs.umass.edu.domain > 192.168.128.200.65514: 18637* 1/5/5 (Class 0) Type2048 (253) (DF)
19:35:54.4294966948 arp who-has 192.168.128.200 tell 192.168.128.199
19:35:54.4294966948 arp reply 192.168.128.200 is-at 0:a0:cc:39:9d:ec
19:36:03.4294966733 192.168.128.199.43205 > 192.168.128.200.1173: S 1929476620:1929476620(0) win 5840 <mss 1460,sackOK,timestamp 697962 0,nop,wscale 6> (DF
)
19:36:03.4294966733 192.168.128.200.1173 > 192.168.128.199.43205: S 1783349897:1783349897(0) ack 1929476621 win 16384 <mss 1460,nop,wscale 0,nop,nop,timest
amp 0 697962>
19:36:03.4294966733 192.168.128.199.43205 > 192.168.128.200.1173: . ack 1 win 92 <nop,nop,timestamp 697962 0> (DF)
19:36:13.4294966727 192.168.128.200.1173 > 192.168.128.199.43205: R 1:1(0) ack 1 win 17520

0 packets received by filter
0 packets dropped by kernel

yyd_iris,

I’m not sure why you think your Linux machine has a port of 1172. It doesn’t. It has a port of 43205 in this example. The client port is always going to be randomly assigned to you by the connect() call.

This part of the dump shows the Linux machine (address 199) asking for the QNX one (200) on the network via the ARP request.

19:35:54.4294966948 arp who-has 192.168.128.200 tell 192.168.128.199
19:35:54.4294966948 arp reply 192.168.128.200 is-at 0:a0:cc:39:9d:ec

Now we see your client (199) on port 43205 connecting to the server (200) on port 1173.

19:36:03.4294966733 192.168.128.199.43205 > 192.168.128.200.1173: S 1929476620:1929476620(0) win 5840 <mss 1460,sackOK,timestamp 697962 0,nop,wscale 6> (DF\
)
19:36:03.4294966733 192.168.128.200.1173 > 192.168.128.199.43205: S 1783349897:1783349897(0) ack 1929476621 win 16384 <mss 1460,nop,wscale 0,nop,nop,timest\
amp 0 697962>
19:36:03.4294966733 192.168.128.199.43205 > 192.168.128.200.1173: . ack 1 win 92 <nop,nop,timestamp 697962 0> (DF)
19:36:13.4294966727 192.168.128.200.1173 > 192.168.128.199.43205: R 1:1(0) ack 1 win 17520

And that’s all I see. The connection looks like it’s been made but I don’t ever see any data sent from the client to the server or the server to the client. I guess this is where the accept call is never returning.

Can you post the actual code in your QNX server side. Not just the psuedo code, but the actual code from where you create the socket through to where you finish getting the connection and spawning threads etc. That might help me spot something.

Tim

Hi Tim,
Thanks!
Sorry about the port 1172 thing. It is confusing. Please ignore it.

Here are the codes of the server (skip codes that deal with errors):

/// *********** Defined structure *************///
typedef int SOCKET_DESC;
typedef struct{
SOCKET_DESC id;
struct sockaddr_in saServer;
}SOCKET_HANDLE_STRUCT;
typedef SOCKET_HANDLE_STRUCT *SOCKET_HANDLE;

///*********** codes *********************///
// create socket
SOCKET_HANDLE listening_socket;
struct hostent *hp;
hp = gethostbyname((char *)(std::string(ServerName).c_str()));
listening_socket = CreateSocket((short) ServerPortNo, hp); // see below for the function that create a socket

// bind and listen
int len = sizeof (struct sockaddr_in);
int status = bind (listening_socket->id, (struct sockaddr *) (&(listening_socket->saServer)), len);
    status = listen(listening_socket->id, 1);

    // accept
SOCKET_HANDLE accepted_socket;
accepted_socket = new SOCKET_HANDLE_STRUCT;	
len=sizeof(struct sockaddr_in);
accepted_socket->id=(SOCKET_DESC)accept(listening_socket->id,(struct sockaddr*)(&(listening_socket->saServer)),&len);

// the function that creates a socket
SOCKET_HANDLE CreateSocket(short nPort, struct hostent* lpHostEntry){
SOCKET_HANDLE theSocket;
struct sockaddr_in* saServer;

theSocket=new SOCKET_HANDLE_STRUCT;
theSocket->id = 0;
saServer = &(theSocket->saServer);

//Create a TCP/IP stream socket
theSocket->id = (SOCKET_DESC)socket(AF_INET,SOCK_STREAM,0);
int opt = 1;
if (setsockopt (theSocket->id, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof (opt)) < 0) {
printf(“setting socket option failed in TCPclient\n”);
}

if(theSocket->id == -1){
PrintNetworkError(“CreateSocket: cannot create socket. Error in socket()”);
free(theSocket);
return NULL;
}

//Fill in the address structure
saServer->sin_family=AF_INET;
saServer->sin_addr=((struct in_addr)(lpHostEntry->h_addr));//Server address
saServer->sin_port = htons(nPort); // Port number
return theSocket;
}

yyd_iris,

Change this:

saServer->sin_addr=((struct in_addr)(lpHostEntry->h_addr));//Server address

to:

saServer->sin_addr = INADDR_ANY;

You don’t need to manually fill in your IP address. That may be causing your problem.

Also, that can’t be real code you posted because I can’t see how:

SOCKET_HANDLE CreateSocket(short nPort, struct hostent* lpHostEntry){ 
SOCKET_HANDLE theSocket; 
struct sockaddr_in* saServer; 

theSocket=new SOCKET_HANDLE_STRUCT; 

This can compile since ‘theSocket’ isn’t a pointer but is instead a structure.

Not to mention this also isn’t real code:

SOCKET_HANDLE listening_socket; 
struct hostent *hp; 
hp = gethostbyname((char *)(std::string(ServerName).c_str())); 
listening_socket = CreateSocket((short) ServerPortNo, hp); // see below for the function that create a socket 

// bind and listen 
int len = sizeof (struct sockaddr_in); 
int status = bind (listening_socket->id, (struct sockaddr *) (&(listening_socket->saServer)), len); 
status = listen(listening_socket->id, 1); 

because once again your treating listening_socket as if it’s a pointer when it’s declared as a structure.

Without seeing the ‘real’ code it’s hard to know if there are other cut/paste mistakes you made. But try the INADDR_ANY first and see if that fixes your problem.

Tim

Tim, SOCKET_HANDLE is a pointer:

 typedef SOCKET_HANDLE_STRUCT *SOCKET_HANDLE;

Change this:
saServer->sin_addr=((struct in_addr)(lpHostEntry->h_addr));//Server address
to:
saServer->sin_addr = INADDR_ANY;
You don’t need to manually fill in your IP address. That may be causing your problem.

why?
maybe yyd_iris wants to listen only on one, selected iface?
/and INADDR_ANY forces “listen on all interfaces”

Hi

I try INADDR_ANY and it does not work.

I only want to connect two computers, one is linux and the other is qnx. Both machines run a Server and a Client. I do this because I don’t know which computer will start the program first. Now I am wondering whether running a Server and a Client cause the problem. I am exzamining it…

Thank you all!

yyd_iris

– after this allocation
theSocket=new SOCKET_HANDLE_STRUCT;

– you have to reset the structure before you fill it, eg:
memset(&theSocket->saServer, 0, sizeof(struct sockaddr_in));

– maybe this command is ok, i dont know
saServer->sin_addr=((struct in_addr)(lpHostEntry->h_addr));//Server address

– but i prefer using this command instead
memcpy(&saServer->sin_addr, lpHostEntry->h_addr, lpHostEntry->h_length);

yyd_iris,

Are you doing this:


Linux                                    QNX
------                                    -----
Server                                Server

Client                                  Client

If so, this is definitely NOT going to do what you expect or want. Only one of those machines should be the server. The other the client. The client machine always connects to the server machine. The server machine only waits for connections.

Then it won’t matter which starts first. If the client starts before the server it will just not be able to connect and will report an error. You can sleep for a bit and then try to connect again.

Tim

heh,
so You don’t want TCP/UDP server <-> client, but p2p <-> p2p (peer2peer) :slight_smile:

anyway - there are so many TCP/UDP examples on the internet (linux, qnx, posix, …);
use google or whatever…

Hi

I know where the problem locates now. Here is the description:

A Linux machine runs a server and the qnx runs a client.
The client program on qnx keeps trying to connect to the server (see the codes below):

int ret = connect(id, (struct sockaddr *)saServer,sizeof(struct sockaddr));
while(ret) {
printf(“socket connect error code: %d\n”, errno);
ret = connect(id,(struct sockaddr *)saServer,sizeof(struct sockaddr));
usleep(100000);
}

If the server run first, the client on qnx has no probolem of connecting to the server.
If the client on qnx runs first, here are the output:

socket connect error code: 261
socket connect error code: 22
socket connect error code: 22
socket connect error code: 22
socket connect error code: 22

It seems after the first failure, the socket has been modified.
Resetting sin_family, sin_addr and sin_port of struct sockaddr seems not helping.
Any idea?
Thanks!

I can post the complete client codes if necessary.

yyd_iris

I know where the problem locates now. Here is the description:

no You don’t :stuck_out_tongue:

socket connect error code: 261

261 = ECONNREFUSED
The attempt to connect was forcefully rejected.

socket connect error code: 22

22 = EADDRINUSE
The address is already in use.

ret = connect(id,(struct sockaddr *)saServer,sizeof(struct sockaddr));

“Protocols such as TCP do not allow further connection requests on a socket after an ECONNREFUSED error. In such a situation, the socket must be closed and a new one created before a subsequent attempt for connection is made.”

qnx.com/developers/docs/6.3. … nnect.html

use man, read more :slight_smile:

Thank you all!

I solve the problem by creating a new socket.

I didn’t realize qnx and linux has diferent error codes… ECONNREFUSED is 111 in linux. My fault