I have the following C program whose main function runTCPConnectivityCheck
opens a TCP socket, sends a string of bytes to it and closes it:
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static int runTCPConnectivityCheck(const int port)
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0)
{
printf("socket failed\n");
return 1;
}
int reuseAddrTrue = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseAddrTrue, sizeof(reuseAddrTrue)) != 0)
{
printf("setsockopt failed\n");
return 1;
}
struct sockaddr_in serv_addr = { 0 };
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) != 1)
{
printf("inet_pton failed\n");
return 1;
}
if (connect(fd, (struct sockaddr*)(&serv_addr), sizeof(serv_addr)) != 0)
{
printf("connect failed\n");
return 1;
}
const char* message = "hello";
const size_t messageLength = strlen(message);
if (send(fd, message, messageLength, 0) != messageLength)
{
printf("send failed\n");
return 1;
}
shutdown(fd, SHUT_RDWR);
close(fd);
return 0;
}
int main()
{
for (int i = 0; i < 10; ++i)
{
printf("%s\n", runTCPConnectivityCheck(5555) == 0 ? "success" : "failure");
//sleep(1);
}
}
If I attempt to test the same port repeatedly, the first call to runTCPConnectivityCheck
works just fine but all subsequent calls fail on the call to connect
. If I add the call to sleep
in, then it also works. Presumably, the 1-second delay gives the network stack sufficient time to clean up the socket so that I can connect to the same port again.
First of all: Am I shutting the socket down properly? Secondly: If I am shutting it down properly, what is the standard way to determine when the network stack is ready to connect to the same host and port again (instead of the lame sleep
I'm using currently)?
Update
More details: connect
is failing with error code 61 or ECONNREFUSED
while strerror
is returning "Connection refused".
The server in this case is the netstat
/nc
command running in a loop on the same machine as the test program:
#!/bin/bash
while true; do
nc -l 5555
done
Program is now C, for real.
The general consensus is that there is nothing particularly wrong with the client code. It turns out that my test server is not able to keep up with my client:
#!/bin/bash
while true; do
nc -l 5555
done
I wrote a forking server in Python which is able to service all of the client connections without difficulty.