Closing TCP connections

Discussion to talk about software related topics only.
User avatar
pbreed
Posts: 1080
Joined: Thu Apr 24, 2008 3:58 pm

Re: Closing TCP connections

Post by pbreed »

dataavail does EXACTLY the same thing as your IsSocketReadable with a lot less internal code...
SeeCwriter
Posts: 606
Joined: Mon May 12, 2008 10:55 am

Re: Closing TCP connections

Post by SeeCwriter »

"dataavail does EXACTLY the same thing as your IsSocketReadable with a lot less internal code..."

Not according to the documentation. And in my experience, it behaves as the documentation says. That is, it returns zero or one indicating data is available or not. If the socket is closed it returns zero, no data available. Even the examples use FD_CLR/SET/ISSET to determine if a connection is pending.
User avatar
pbreed
Posts: 1080
Joined: Thu Apr 24, 2008 3:58 pm

Re: Closing TCP connections

Post by pbreed »

Code from dataavail.. (in iosys.,cpp)

int dataavail( int fd )
{
if ( fd < 3 ) //Is it stdio?
{
return charavail();
}
return (FD_ISSET( fd, &read_file_sets )!=0);
}


Your select is only looking at the read data, not error, so identical to dataavail with a lot less code...
(P.S. I personally wrote all of this library code..)
SeeCwriter
Posts: 606
Joined: Mon May 12, 2008 10:55 am

Re: Closing TCP connections

Post by SeeCwriter »

So your just talking about detecting a pending tcp connection. How does the file descriptor become associated with read_file_sets? Do I need to call SetDataAvail after doing a listen, or is it taken care of automatically behind the curtain?

If this works as you say, why don't the examples show this method of detecting a connection? It would be a lot simpler.
User avatar
pbreed
Posts: 1080
Joined: Thu Apr 24, 2008 3:58 pm

Re: Closing TCP connections

Post by pbreed »

I'm a tiny bit confused about your question, many things in this thread...
You've used socket interchangeably for both listening socket and accepted/connected socket.
They are really differnt things .....

You are trying to determine:
1)If your listening socket has a connection waiting to accept?
(dataavail works for this, alas the traditional accept with a dedicated task is the usual way as the one task services both the listen and the accepted sockets.)

2)Trying to determine if an already accepted/connected socket has data.
(Both select and dataavail work for this)

3)Trying to determine if a socket has been closed by the other side....
When doing this you ALWAYS need to check for data before you check for close...
Other side could send data then close....socket will both indicate its closing AND have dataavailible to read. (The data the other side sent before closing)

You can do all of this inside one big polling loop, alas this is not the recommended way. Recomended way to to separate things out into tasks...
That way in the future if you do something like use SSL for security that can take 10 seconds do do an accept
your other embedded processing can continue...
SeeCwriter
Posts: 606
Joined: Mon May 12, 2008 10:55 am

Re: Closing TCP connections

Post by SeeCwriter »

That's good information. We aren't using SSL yet, but we are getting requests for it, so it's only a matter of time.

Regarding your point 1, how does the listening socket (fd) become part of read_file_sets? Do I call SetDataAvail, or is it taken care of automatically?

Regarding point 2, we are in agreement. We use dataavail to determine if data is waiting to be read from a connected socket.

Regarding point 3, can I use your function haserror on an already connected socket to determine if the other side has closed the socket? If so, how do I associate the socket file descriptor with error_file_sets? Do I call SetHaveError, or is it taken care of automatically?
SeeCwriter
Posts: 606
Joined: Mon May 12, 2008 10:55 am

Re: Closing TCP connections

Post by SeeCwriter »

I tried what you recommended. However, when a tcp connection is made (accepted), the module immediately closes the connection.
Here is the code. Did I implement it right?

Code: Select all

#define MAX_CONNECTS	12
struct _sockets {
  int fd[MAX_CONNECTS];	// these get set to -1 on power-up.
  IPADDR ip[12];
};
_sockets sockets;


void Checktcp( int &listener, nt port )
{
	IPADDR addr;
	int i, num_free, connected=0;

	// Check for closed sockets and count # connections.
	for( i = 0; i < MAX_CONNECTS; i++ )
	{
		if ( sockets.fd[i] < 0 ) continue;
		else if ( haserror(sockets.fd[i]) ) 
		{
			close( sockets.fd[i] );
			ClrHaveError( sockets.fd[i] );
			sockets.fd[i] = -1;
		}
		else ++connected;
	}
	num_free = MAX_CONNECTS - connected;

	if ( listener < 0 && num_free > 0 )
	{
		listener = listen( INADDR_ANY, (WORD) port, 5 );
		SetDataAvail( listener );
		return;
	}

	if ( num_free <= 0 ) return;	// full up, bail...

	// is there a connection pending?
	if ( !dataavail( listener ) )  return;

	int new_fd = accept( listener, &addr, NUL, 0 );	// should be a pending connection.

	if ( new_fd <= 0 ) return;

	for ( i = 0; i < MAX_CONNECTS; i++ )
	{
		if ( sockets.fd[i] < 0 )
		{
			sockets.fd[i] = new_fd;
			sockets.ip[i] = addr;
			SetHaveError( new_fd );
			break;
		}
	}
}
SeeCwriter
Posts: 606
Joined: Mon May 12, 2008 10:55 am

Re: Closing TCP connections

Post by SeeCwriter »

Following up on my previous post. The socket is closing because of function haserror. It looks like the function returns true if the file descriptor has been added to the error fd_set, not because an error has been detected with the file descriptor. So it will always return true if the socket is open and the socket will be immediately closed after it's opened. haserror appears to work differently than dataavail. dataavail returns true if there is data waiting to be read from the file descriptor, not because the file descriptor has been added to the read fd_set. Yet both functions use FD_ISSET to make that determination. So I'm confused. What I had worked, so I'm returning to it.
User avatar
TomNB
Posts: 538
Joined: Tue May 10, 2016 8:22 am

Re: Closing TCP connections

Post by TomNB »

I realize you are going back to your previous method, but just in case anyone else comes across this thread and is interested in select(), there is an example in the 2.8.x releases: \nburn\examples\StandardStack\TCP\TcpMultiSocket
SeeCwriter
Posts: 606
Joined: Mon May 12, 2008 10:55 am

Re: Closing TCP connections

Post by SeeCwriter »

I did look at the example, which my function Checktcp I posted early was based on. In my case, I can't use any functions that are going to block, unless I can determine beforehand whether the event the blocking function is waiting for is already present, such as the accept function. I never call accept unless a call to ZeroWaitSelect indicates an event is pending.

When I look at example TcpMultiSocket, and compare that with the functions in iosys.cpp, I get confused. I'm easily confused, so don't take that as a critique of the code.

In the example, FD_ISSET seems to be used to determine if a particular event has occurred. But when I look at the functions in iosys.cpp, FD_ISSET seems to be designed to determine if a particular fd has been added to a particular fd_set. Even the RunTimeLibrary manual states that FD_ISSET "indicates whether (or not) a specific fd is in a specific fd_set." And if you look at functions FD_CLR, FD_SET, and FD_ISSET, they are all using nearly identical code to manipulate bits in the same fd_set, using a mask created from the value of the fd. The CLR & SET functions are clearing or setting a particular bit, and the ISSET function is testing the bit and returning the result. All consistent with the manual description. So I don't see how the ISSET can be used to determine if an event has occurred. And yet, dataavail does seem to indicate when data is available to be read, and it uses FD_ISSET to make that determination. However, using function haserror to try to determine if an error has occurred with a particular fd does not work. It always returns true, which is consistent with how I think ISSET works. Can you see my confusion?
Post Reply