Winsock blocking recv() not return, while WireShark says there are incoming segments in the TCP stream - tcp

I am working with some protocol on my Windows 10 pro with VC++ 2013 Community, basically includes three steps:
client sends a GET header (e.g. authentication, etc)
server returns a HTTP header (e.g. status code 200 if everything is fine)
then server keeps sending binary data stream after the HTTP header
I send the header, and call recv() in blocking mode to receive data from server through the TCP stream. However, the recv() blocks, never return.
I use WireShark to "follow" the TCP stream, and it shows that server does keep sending binary data, and I do see ACK message from client side to acknowledge every segment it receives. However, recv() still blocks, and never returns.
I tried to use:
pure C implementation over WinSock
C# using TcpClient
C++ with Boost Asio
non-blocking WinSock (as in this article)
The first version was implemented in WinHTTP, and eventually got Timeout.
None of them can receive any data. However, the WireShark can still tell that the server keeps sending binary data.
I tried to turn off my firewall, but the problem still there.
The most weird thing is my first implementation actually did successfully get data from recv(), about two days ago. On that day, recv() returned three times, and then blocked again. The next day, the same implementation, recv() never be able to return anything.
I am really confused. Thank you!
Here is the code, blocking Winsock version:
WSADATA wsaData;
int iResult;
SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in clientService;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
//----------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
//----------------------
// Create a SOCKET for connecting to server
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
clientService.sin_family = AF_INET;
auto ip = gethostbyname(name);
clientService.sin_addr = *(reinterpret_cast<struct in_addr *>(ip->h_addr));
clientService.sin_port = htons(DEFAULT_PORT);
//----------------------
// Connect to server.
iResult = connect(ConnectSocket, (SOCKADDR*)&clientService, sizeof(clientService));
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
printf("Unable to connect to server: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Send an initial buffer
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR) {
printf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if (iResult > 0)
printf("Bytes received: %d\n", iResult);
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
} while (iResult > 0);
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;

Since the shutdown code is a copy/paste from the microsoft page (https://msdn.microsoft.com/en-us/library/windows/desktop/ms740121(v=vs.85).aspx) - I suppose that is how they indicate sending has completed. I believe this explains the issue you're having (from the above page):
Note When issuing a blocking Winsock call such as recv, Winsock may need to wait for a network event before the call can complete. Winsock performs an alertable wait in this situation, which can be interrupted by an asynchronous procedure call (APC) scheduled on the same thread. Issuing another blocking Winsock call inside an APC that interrupted an ongoing blocking Winsock call on the same thread will lead to undefined behavior, and must never be attempted by Winsock clients.
I actually just realized that I've only ever used non-blocking sockets and always have the receiving code on its own thread. So try adding this:
iResult = ioctlsocket(m_socket, FIONBIO, &iMode);
From here:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms738573(v=vs.85).aspx
Note: You're going to get mostly a series of failed attempts to receive data from the socket - so you'll need to handle those and you'll also not want to tight loop.

Related

STM32 LwIP Delay in netconn_write

I implemented a small tcp client on STM32F7 with freeRtos and LwIP and netconn api.
I can establish a connection with the server and send some data to the network. My problem is a huge delay between the command and when I can actually see the ethernet data on the network (seconds..). Seems like the data is buffered before sending it in one go.
I'm aware of the TCP_NODELAY flag and I set it (with tcp_nagle_disable(conn->pcb.tcp)), but it doesn't make a difference. Ethernet payload is around 50 bytes, TCP_MSS is 1460.
The netconn api sees the data as sent (netbuffer structure is updated, tcp_write() and tcp_output() are called with no errors), but I have the impression that after low_level_output() is called and the data buffer is passed to the DMA (with HAL_ETH_TransmitFrame()) it stays there until something happened and 3 or 4 ethernet packets are sent in a go.
I don't want to wait forever for a reply and I set a timeout on netconn_recv(), enabling LWIP_SO_RCVTIMEO and calling netconn_set_recvtimeout(). I set up the server to answer with an echo but even with a timeout of 500ms I loose most of the replies.
Here some code:
conn = netconn_new(NETCONN_TCP);
if (conn != NULL)
{
err = netconn_bind(conn, IP_ADDR_ANY, 0);
if (err == ERR_OK)
{
connect_error = netconn_connect(conn, &dest_addr, SRV_PORT);
if (connect_error == ERR_OK)
{
// set a timeout to avoid waiting forever
netconn_set_recvtimeout(conn, 500);
//TCP_NODELAY
tcp_nagle_disable(conn->pcb.tcp);
osSemaphoreRelease(tcpsem); // signal tcpsend
if (netconn_recv(conn, &buf) == ERR_OK)
{
//Parse message
do
{
// do stuff..
}
while (netbuf_next(buf) >0);
netbuf_delete(buf);
} else {
// TIMEOUT
}
}
/* Close connection */
netconn_close(conn);
}
netconn_delete(conn);
}
vTaskDelete(tcpsendTaskHandle);
vTaskDelete(NULL);
tcpsend
void tcpsend (void *data, size_t len)
{
// send the data to the connected connection
netconn_write(conn, data, len, NETCONN_NOFLAG);
}
tcpsend
static void tcpsend_thread (void *arg)
{
for (;;)
{
// semaphore must be taken before accessing the tcpsend function
osSemaphoreAcquire(tcpsem, portMAX_DELAY);
// build msg
if (ethPrepare(&ethMsg) == ERR_OK)
{
// send the data to the server
tcpsend(&ethMsg, ethMsg.ncSize);
}
vTaskDelay(100);
}
}
Found the problem:
I forgot to set also the TxBuffer memory as not cacheable bufferable..
Once I added the memory configuration on the loader script and in ethernetif.c also for the tx buffer (I had it only for he rx) I could see the ethernet packets right away.

ESP32 TCP client

I want to set up TCP server on windows and TCP client on ESP32. Main idea is to send String to ESP32 change it and send it back to server, but I'm really new with all of this stuff and got stuck on setting up TCP client on ESP32. Examples or references would be really helpful.
int create_ipv4_socket()
{
struct addrinfo hints;
struct addrinfo *res;
struct in_addr *addr;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
int err = getaddrinfo(UDP_IPV4_ADDR, TCP_PORT, &hints, &res);
if(err != 0 || res == NULL) {
printf("DNS lookup failed err=%d res=%p\n", err, res);
return -1;
}
/* Code to print the resolved IP.
Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */
addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
printf("DNS lookup succeeded. IP=%s\n", inet_ntoa(*addr));
l_sock = socket(res->ai_family, res->ai_socktype, 0);
if(l_sock < 0) {
printf("... Failed to allocate socket.\n");
freeaddrinfo(res);
return -1;
}
struct timeval to;
to.tv_sec = 2;
to.tv_usec = 0;
setsockopt(l_sock,SOL_SOCKET,SO_SNDTIMEO,&to,sizeof(to));
if(connect(l_sock, res->ai_addr, res->ai_addrlen) != 0) {
printf("... socket connect failed errno=%d\n", errno);
close(l_sock);
freeaddrinfo(res);
return -1;
}
printf("... connected\n");
freeaddrinfo(res);
// All set, socket is configured for sending and receiving
return l_sock;
}
From this forum https://www.esp32.com/viewtopic.php?t=5965
How do you communicate with your ESP? if you communicate through UART, just send him AT command he need by writing on the UART port:
"AT+CIPSTATUS\r\n"
and then wait for his response.
If you are connected to your ESP32 directly with your computer, just use putty and directly send AT command to it.
A non exhaustive list of AT's command can be found here:
https://www.espressif.com/sites/default/files/documentation/esp32_at_instruction_set_and_examples_en.pdf

QUdpSocket broadcast till answered

I'm implementing a simple UDP server-client app. The main logic is: server starts sending broadcast -> clients responses -> server stops sending broadcast and performs some work.
I'm stuck with broadcasting loop:
sUDP::sUDP(QObject *parent) : QObject(parent)
{
serverSocket = new QUdpSocket(this);
serverIp = new QHostAddress("192.168.1.2");
pickUpThePhone = false;
if(serverSocket->state() != serverSocket->BoundState){
if (!serverSocket->bind(*serverIp, 4321)) {
qFatal("Error binding server");
}
}
connect(serverSocket,SIGNAL(readyRead()), SLOT(readSocket()));
while(!pickUpThePhone){
QByteArray Data;
Data.append("server");
serverSocket->writeDatagram(Data, Data.size(), QHostAddress("192.168.255.255"), 1234);
}
}
actually signal readyRead() never emitted and so broadcasting never stops:
void sUDP::readSocket()
{
qDebug() << "read";
while(serverSocket->hasPendingDatagrams()){
QByteArray buffer;
buffer.resize(serverSocket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
serverSocket->readDatagram(buffer.data(), buffer.size(), &sender, &senderPort);
if(strcmp(buffer.data(),"stop") == 0){
pickUpThePhone = true;
}
}
}
The client works as it should - it responses to the datagram with "server" with "stop" message, but it looks like the while-loop is never interrupted.
Any help will be useful, thank you.
It doesn't work because your program is busy sending broadcasts. Your while loop will not let the Qt event-loop perform its work and therefore your program can't do anything else.
You're also sending broadcasts constantly, your computer will do nothing else than spam the network.
The solution to both problems is a timer. Create a repeating timer that once every second (ore more or less) sends out the broadcast. Stop or pause the timer when you get a response.

Microchip TCPIP keep alive not works

i'm trying to build a server with a PIC24F.
This is a piece of code i'm isuing:
switch(TCPServerState) {
case SM_HOME:
// Allocate a socket for this server to listen and accept connections on
socket.Socket = TCPOpen(0, TCP_OPEN_SERVER, SERVER_PORT, TCP_PURPOSE_GENERIC_TCP_SERVER);
if(socket.Socket != INVALID_SOCKET) {
TCPServerState = SM_LISTENING;
}
break;
case SM_LISTENING:
// See if anyone is connected to us
//if(TCPIsConnected(socket.Socket)) {
if(!TCPWasReset(socket.Socket)){
if(socket.Connected == 0) {
socket.Connected = 1;
printf("Socket is CONNECTED: %d\n", socket.Socket);
}
uint16_t avaible = TCPIsGetReady(socket.Socket);
// Some stuff
}
else if(socket.Connected == 1){
printf("Socket RESET: %d\n", socket.Socket);
TCPServerState = SM_CLOSING;
}
break;
case SM_CLOSING:
// Close the socket connection.
socket.Connected = 0;
TCPClose(socket.Socket);
TCPServerState = SM_HOME;
printf("Socket is CLOSED: %d\n", socket.Socket);
break;
}
All works fine if i close my client socket properly, but if i disconnect ethernet cable i am not able to detect disconnection and my code does not close the socket because TCPWasReset still FALSE(or TCPIsConnected still TRUE).
So how can i detect the disconnection of network cable(without add a software keep_alive implementation) ?
Thanks
Check a few items:
Call TickInit(); before StackInit();
Select the correct TIMER1 clock source for your application - internal clock or external clock (T1CON.TCS)
Otherwise, just use a debugger on the keepalive logic in TCP.C, which should default to 10 seconds in the latest Microchip Library for Applications TCP/IP stack 5.42.08.

TCP server accept call does not return

We need some help with a TCP client server code. The client timesout from its connect call and the server does not return from accept. Here's the strace.
strace -p 7167 -p 7168 -p 7297
Process 7167 attached - interrupt to quit
Process 7168 attached - interrupt to quit
Process 7297 attached - interrupt to quit
[pid 7167] accept(4, <unfinished ...>
[pid 7168] accept(4, <unfinished ...>
[pid 7297] connect(3, {sa_family=AF_INET, sin_port=htons(24465), sin_addr=inet_addr("215.47.142.168")}, 16
We rebooted the system but the problem persists even immediately after reboot.
Could it be a SYN Flood problem. How do we deal with such connections? Also, do the half made connections queue up in the listen queue(argument 2 of listen call) and stop any further accepts from any client OR does the TCP some how blocks that particular client only.
Here's the code...
client.all this is inside a function that returns socket
int sock = socket(nmspace,style,protocol);
int ret;
struct hostent *hinfo;
if(sock<0){
printf("Error occurred while creating socket:%d\n",sock);
printf("%s\n",strerror(errno));
return -1;
}
memset(&dest, 0, sizeof(struct sockaddr_in));
hinfo = gethostbyname(rmserver);
if(hinfo == NULL)
printf("getbyname failed!\n");
dest.sin_family = AF_INET;
dest.sin_addr = *(struct in_addr *)(hinfo->h_addr);
dest.sin_port = htons(port);
ret = connect(sock, (struct sockaddr *)&dest, sizeof(struct sockaddr));
if(ret<0){
printf("Error occurred while connecting on the socket:%d\n",sock);
printf("%s\n",strerror(errno));
close(sock);
return -1;
}
server
making the server socket...all this is inside a function that returns the socket>>>>>>
struct sockaddr_in serv;
int mysocket,r;
mysocket = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv, 0, sizeof(struct sockaddr_in));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = INADDR_ANY;
serv.sin_port = htons(port);
r = bind(mysocket, (struct sockaddr *)&serv, sizeof(struct sockaddr));
if(r<0) {
printf("Error occurred binding the socket:%d to the server port:%d\n",mysocket,port);
printf("%s",strerror(errno));
close(mysocket);
return -1;
}
r = listen(mysocket, 5);
if(r<0) {
printf("Error occurred while enabling listen on the socket:%d\n",mysocket);
printf("%s",strerror(errno));
close(mysocket);
return -1;
}
server accept call>>>>>>
struct sockaddr_in dest;
int socksize=sizeof(struct sockaddr_in);
int consocket;
consocket = accept(sock, (struct sockaddr *)&dest, (socklen_t *)&socksize);
if(consocket<0) {
printf("Error occurred while accepting on the socket:%d\n",sock);
printf("%s\n",strerror(errno));
}
Not using select. I hope we don't need that as the sockets are by default blocking.
cheers...raman
Your client should be using connect (man page) rather than accept. Servers use accept to accept incoming connections and to get a new socket unique to that connection, leaving the original file descriptor free for listening and accepting new connections. Clients just use the same socket after the connection is made.
Also, I recommend taking a look at how to use select (man page).

Resources