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

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.

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.

C++ UDP sendto fails, needs sleep

I have a UDP client C++ code - based on WSA sockets - that works well. The code was originally written in VS6 and I recently recompiled it in VS2010 for 64bit environment, with only little adjustments.
Now, the sendto() fails to send something, if there is no Sleep(..) or any equivalent delay after the sendto() and before closesocket(). "Fails" means, that sendto() returns the proper amount of data, but I see no message on the network (I used wireshark to check this).
This is my code:
void CTest::SendHello()
{
SOCKET sSocket;
sSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(m_strDstIpAddr);
addr.sin_port = htons(m_nTxPort);
int nMsgLen = 8;
char pTxBuffer[8];
*((DWORD*) &pTxBuffer[ 0]) = 0x11223344;
*((DWORD*) &pTxBuffer[ 4]) = 0;
int nSent = sendto(sSocket, pTxBuffer, nMsgLen, 0, (struct sockaddr *) &addr, sizeof(addr));
Sleep(10); // <- this seems to be necessary
if (nSent != nMsgLen)
{
CString s = "error sending HELO\n";
AfxMessageBox(s);
}
closesocket(sSocket);
}
Without the Sleep(), the code does not send anything, yet it returns no errors. With the Sleep() it works. Also, this is happens in release version, when compiled for debug, the code also works without the Sleep().
It seems, as if the closesocket() shuts the socket down, before the message is finally sent, but I thought sendto() is a synchronous function. I tried using SO_LINGER, but this is not applicable for SOCK_DGRAM sockets.
Since the code is inside a DLL, I can't create the socket in ctor and delete it in the dtor, because SendHello() might be called from different thread contexts, and I like to avoid to make the code too complicated.
thanks for any help
With UDP there is no ordering of data between the sender and receiver and data sent using UDP datagram sockets isn't guaranteed to arrive. All sleep is doing in your case is practically providing enough time for the data to arrive at the other end. If you want confirmation of receipt and error checking, then you can either code a scheme for UDP or use TCP. In fact, you can turn off the server completely and your client will happily fire UDP packets out without error even though there is nobody listening.
to insure a connection, look at connect(). Nothing prevents using connect with UDP and you can then use send() recv().

C/C++ server not sending last few lines of file

I am writing a simple server in C/C++. I have everything mostly complete, but there is one problem. The server fails to send the last three lines of a file to a client. I assume I am closing the socket connection prematurely, but my attempts to remedy this have failed. For example, calling
shutdown(clientSckt, SHUT_RDWR);
right before calling the close() method for the client socket. And adding a latency to the socket parameters like so:
struct linger l;
l.l_onoff = 1;
l.l_linger = 1;
setsockopt(clientSckt, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
after it has been opened. But neither of these seem to work. The server writes everything with no errors, but the client is not receiving everything.
From vague memory:
a) if you want to use SO_LINGER, use close().
b) more robust is do a half shutdown
shutdown(clientSckt, SHUT_WR)
and then read() until you get a 0.
It turns out, I forgot to add the character length of the header to the length of the file I was sending over. Hence, the client was closing the connection before the server had sent everything over.

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.

FD_SET Problem/Networking

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.