FD_SET Problem/Networking - c++

hi right now im trying to know if a client or the server disconnected and then send an error but i cant seem to make it work and ive got no idea how to do this so i really need help plz
here's my code
#ifdef _WIN32 || _WIN64
if(select(0,&fd_read,NULL,&fd_close,&time)==-1){
printf("Error in Select()");
return 0;
}
#else
if(select(sockMax + 1,&fd_read,NULL,&fd_close,&time)==-1){
printf("Error in Select()");
return 0;
}
#endif
if(FD_ISSET(socklisten,&fd_read)){
}
else
{
dopack(&pkt);
send(socklisten, (char*)&pkt, sizeof(pack), 0);
}
//this is where the error shows -----------
if(FD_SET(socklisten,&fd_close))
{
backtoMenu = true;
}
FD_ZERO(&fd_leer);
FD_SET(sockEscucha,&fd_leer);
The error says expected primary-expression before 'do'
so yeah i've got no idea what that means
and just in case this is how im declaring fd_read and fd_close
fd_set fd_read;
fd_set fd_close;
plz any help would be really appreciated tyvm

What Richard said, in addition, the third fd_set passed to select() is not about closed FDs, but rather about some exceptional condition that requires special attention (which exactly, is defined by the underlying driver, for example, TCP sockets use it for "urgent" data.
You detect a remote close by the return code from recv(), i.e. inside the handling for readable descriptors. If recv() on a stream socket returns 0, the remote side has closed the connection (with TCP, you can still send data as only one direction is closed); if recv() returns -1, then errno has further information, for example ECONNRESET means that a TCP RST packet was received.

You want to use if(FD_ISSET(...
To determine if a client has closed, you want to read from an active readfd and see if the read returns zero.

Related

UnrealEngine4: Recv function would keep blocking when TCP server shutdown

I use a blocking FSocket in client-side that connected to tcp server, if there's no message from server, socket thread would block in function FScoket::Recv(), if TCP server shutdown, socket thread is still blocking in this function. but when use blocking socket of BSD Socket API, thread would pass from recv function and return errno when TCP server shutdown, so is it the defect of FSocket?
uint32 HRecvThread::Run()
{
uint8* recv_buf = new uint8[RECV_BUF_SIZE];
uint8* const recv_buf_head = recv_buf;
int readLenSeq = 0;
while (Started)
{
//if (TcpClient->Connected() && ClientSocket->GetConnectionState() != SCS_Connected)
//{
// // server disconnected
// TcpClient->SetConnected(false);
// break;
//}
int32 bytesRead = 0;
//because use blocking socket, so thread would block in Recv function if have no message
ClientSocket->Recv(recv_buf, readLenSeq, bytesRead);
.....
//some logic of resolution for tcp msg bytes
.....
}
delete[] recv_buf;
return 0
}
As I expected, you are ignoring the return code, which presumably indicates success or failure, so you are looping indefinitely (not blocking) on an error or end of stream condition.
NB You should allocate the recv_buf on the stack, not dynamically. Don't use the heap when you don't have to.
There is a similar question on the forums in the UE4 C++ Programming section. Here is the discussion:
https://forums.unrealengine.com/showthread.php?111552-Recv-function-would-keep-blocking-when-TCP-server-shutdown
Long story short, in the UE4 Source, they ignore EWOULDBLOCK as an error. The code comments state that they do not view it as an error.
Also, there are several helper functions you should be using when opening the port and when polling the port (I assume you are polling since you are using blocking calls)
FSocket::Connect returns a bool, so make sure to check that return
value.
FSocket::GetLastError returns the UE4 Translated error code if an
error occured with the socket.
FSocket::HasPendingData will return a value that informs you if it
is safe to read from the socket.
FSocket::HasPendingConnection can check to see your connection state.
FSocket::GetConnectionState will tell you your active connection state.
Using these helper functions for error checking before making a call to FSocket::Recv will help you make sure you are in a good state before trying to read data. Also, it was noted in the forum posts that using the non-blocking code worked as expected. So, if you do not have a specific reason to use blocking code, just use the non-blocking implementation.
Also, as a final hint, using FSocket::Wait will block until your socket is in a desirable state of your choosing with a timeout, i.e. is readable or has data.

Winsock - Client disconnected, closesocket loop / maximum connections

I am learning Winsock and trying to create some easy programs to get to know it. I managed to create server which can handle multiple connections also manage them and client according to all tutorials, it is working how it was supposed to but :
I tried to make loop where I check if any of clients has disconnected and if it has, I wanted to close it.
I managed to write something which would check if socket is disconnected but it does not connect 2 or more sockets at one time
Anyone can give me reply how to make working loop checking through every client if it has disconnected and close socket ? It is all to make something like max clients connected to server at one time. Thanks in advance.
while (true)
{
ConnectingSocket = accept (ListeningSocket, (SOCKADDR*)&addr, &addrlen);
if (ConnectingSocket!=INVALID_SOCKET)
{
Connections[ConnectionsCounter] = ConnectingSocket;
char *Name = new char[64];
ZeroMemory (Name,64);
sprintf (Name, "%i",ConnectionsCounter);
send (Connections[ConnectionsCounter],Name,64,0);
cout<<"New connection !\n";
ConnectionsCounter++;
char data;
if (ConnectionsCounter>0)
{
for (int i=0;i<ConnectionsCounter;i++)
{
if (recv(Connections[i],&data,1, MSG_PEEK))
{
closesocket(Connections[i]);
cout<<"Connection closed.\n";
ConnectionsCounter=ConnectionsCounter-1;
}
}
}
}
Sleep(50);
}
it seems that you want to manage multiple connections using a single thread. right?
Briefly socket communication has two mode, block and non-block. The default one is block mode. let's focus your code:
for (int i=0;i<ConnectionsCounter;i++)
{
if (recv(Connections[i],&data,1, MSG_PEEK))
{
closesocket(Connections[i]);
cout<<"Connection closed.\n";
ConnectionsCounter=ConnectionsCounter-1;
}
}
In the above code, you called the recv function. and it will block until peer has sent msg to you, or peer closed the link. So, if you have two connection now namely Connections[0] and Connections[1]. If you were recv Connections[0], at the same time, the Connections[1] has disconnected, you were not know it. because you were blocking at recv(Connections[0]). when the Connections[0] sent msg to you or it closed the socket, then loop continue, finally you checked it disconnect, even through it disconnected 10 minutes ago.
To solve it, I think you need a book Network Programming for Microsoft Windows . There are some method, such as one thread one socket pattern, asynchronous communication mode, non-block mode, and so on.
Forgot to point out the bug, pay attention here:
closesocket(Connectons[i]);
cout<<"Connection closed.\n";
ConnectionsCounter=ConnectionsCounter-1;
Let me give an example to illustrate it. now we have two Connections with index 0 and 1, and then ConnectionsCount should be 2, right? When the Connections[0] is disconnected, the ConnectionsCounter is changed from 2 to 1. and loop exit, a new client connected, you save the new client socket as Connections[ConnectionsCounter(=1)] = ConnectingSocket; oops, gotting an bug. because the disconnected socket's index is 0, and index 1 was used by another link. you are reusing the index 1.
why not try to use vector to save the socket.
hope it helps~

Check if socket is connected or not [duplicate]

This question already has answers here:
How to find the socket connection state in C?
(12 answers)
Closed 7 years ago.
I have an application which needs to send some data to a server at some time. The easy way would be to close the connection and then open it again when I want to send something. But I want to keep the connection open so when I want to send data, I first check the connection using this function:
bool is_connected(int sock)
{
unsigned char buf;
int err = recv(sock,&buf,1,MSG_PEEK);
return err == -1 ? false : true;
}
The bad part is that this doesn't work. It hangs when there is no data to receive. What can I do? How can I check if the connection is still open?
Don't check first and then send. It's wasted effort and won't work anyway -- the status can change between when you check and when you send. Just do what you want to do and handle the error if it fails.
To check status, use:
int error_code;
int error_code_size = sizeof(error_code);
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size);
You need to enable non-blocking behavior, by setting O_NONBLOCK using fcntl. One easy but non-standard way to do a non-blocking read would be to use:
recv(sock, &buf, 1, MSG_PEEK | MSG_DONTWAIT);
Afterwards, you must check errno if it fails. It can fail with EAGAIN or it can fail with EBADF or ENOTCONN etc.
Obviously, the simplest and cleanest way to deal with this would be to avoid "forgetting" if the socket is connected or not. You'll notice if the socket becomes disconnected once a recv returns 0 or a send returns EPIPE.
Default use of TCP doesn't allow very timely detection of dead sockets (outside of normal closure) so I'll suggest that an "is_connected" function like this is largely useless for all practical purposes. Consider implementing an application-layer keep-alive and track if it's alive based on timely responses (or lack thereof).
edit: after posting i see BoBTFish's link, which is effectively the same thing.

Socket select() Handling Abrupt Disconnections

I am currently trying to fix a bug in a proxy server I have written relating to the socket select() call. I am using the Poco C++ libraries (using SocketReactor) and the issue is actually in the Poco code which may be a bug but I have yet to receive any confirmation of this from them.
What is happening is whenever a connection abruptly terminates the socket select() call is returning immediately which is what I believe it is meant to do? Anyway, it returns all of the disconnected sockets within the readable set of file descriptors but the problem is that an exception "Socket is not connected" is thrown when Poco tries to fire the onReadable event handler which is where I would be putting the code to deal with this. Given that the exception is silently caught and the onReadable event is never fired, the select() call keeps returning immediately resulting in an infinite loop in the SocketReactor.
I was considering modifying the Poco code so that rather than catching the exception silently it fires a new event called onDisconnected or something like that so that a cleanup can be performed.
My question is, are there any elegant ways of determining whether a socket has closed abnormally using select() calls? I was thinking of using the exception message to determine when this has occured but this seems dirty to me.
I had this same problem. The only way to get around it is to control the client applications exit code. The solution that I used was to send a shutdown signal before the reactor was terminated on the client side. Then on the server you simply close the socket.
//Client:
//Handler Class: onWrite
Packet p = Packet::Shutdown();
if (p.fn == "shutdown")
{
_reactor.stop();
delete this;
}
//Server
//Accepter Class: onRead
if (p.fn == "shutdown")
{
printf("%s has disconnected", _username.c_str());
_socket.close();
delete this;
}
It appears you are correct Remy. I managed to distinguish whether the socket had disconnected using the following code (this was added to Poco/Net/src/SocketImpl.cpp):
bool SocketImpl::isConnected()
{
int bytestoread;
int rc;
fd_set fdRead;
FD_ZERO(&fdRead);
FD_SET(_sockfd, &fdRead);
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 250000;
rc = ::select(int(_sockfd) + 1, &fdRead, (fd_set*) 0, (fd_set*) 0, &tv);
ioctl(FIONREAD, &bytestoread);
return !((bytestoread == 0) && (rc == 1));
}
From my understanding, this checks if the socket is readable using a call to select() and then checks the actual number of bytes which are available on that socket. If the socket reports that it is readable but the bytes are 0 then the socket is not actually connected.
While this answers my question here, this unfortunately has not solved my Poco problem as I can't figure out a way to fix this in the Poco SocketReactor code. I tried making a new event called DisconnectNotification but unfortunately cannot call that as the same error gets thrown as does for a ReadNotification on a closed socket.
Just catch the ConnectionResetException in OnReadable() (processes the ReadableNotification)
Then it handles "Connection reset by peer" properly.
catch(Poco::Net::ConnectionResetException &ex)
{
_socket.shutdownSend();
delete this;
}

Non-blocking socket on Windows doesn't return after send() call

I'm hoping someone can explain a situation -- any situation -- in which a non-blocking Windows socket would not immediately return after using send() on it. On other platforms, my code works as intended, so it appears to be a Windows-specific issue.
The way I can tell it isn't returning is quite simple: I cout a message immediately before and after the send() function, and upon running, the console only shows the first message. I can't seem to reproduce it in a simplified example, so I apologize for the lack of code. I will try to provide more specifics if necessary.
Edit:
The specific code where the socket is created and set as non-blocking is the following. I'm assuming that there is indeed no way a non-blocking socket would behave this way, and that something else is causing it to stop before the second message is shown. Thank you for your help anyway...I will try my best to get to the bottom of it, but right now I'm quite mystified.
SOCKET new_sock = accept(sock, (struct sockaddr*)&addr, &addr_size);
#ifdef _WIN32
unsigned long ul;
ioctlsocket(new_sock, FIONBIO, &ul);
#else
fcntl(new_sock,F_SETFL,O_NONBLOCK);
#endif
setsockopt(new_sock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg));
setsockopt(new_sock, SOL_SOCKET, SO_OOBINLINE, (unsigned char *)&opt, sizeof(int));
if this is the actual code, you havn't initialized ul . Do:
unsigned long ul = 1;
ioctlsocket(new_sock, FIONBIO, &ul);
If your "cout" message display does not contain an std::endl, the call might not be blocking without you noticing !
Send will block on filling the ip stack buffers on a connected socket. If you have a connected socket and you start throwing data at it faster then the ip stack can roll it out the wire with the attendant ack nak paddywacks then the send will block.
I have not seen that properly set non blocking sends will block though. They will error with wouldblock. So I would look to how you are setting non blocking io. Are you sure you are setting non blocking on the resultant socket not the base socket... ie the socket returned from the accept.