Socket sendto() fails errno 88 and 9 - sockets

I'm trying to run a simple client-server application using UDP (as an exercise), OS Linux Mint 14.
Client sends a request to the server, when starting, to get a few session parameters, including a timeout in usec.
The client opens a socket and sets a default timeout value, in order non to be blocked indefinetly on recvfrom, then sends a request for those parameters, closes said socket, re-opens a socket setting the new timeout value, and finally asks the user for commands.
The parameters request is dealt with by a subfunction which gets, among other things, a pointer to the client socket, so that the main function will be able to reference the new socket as well, should the new sockfd be a different number.
(Return value is used as a check value, zero or non-zero)
The sequence is:
client calls for subfunction passing socket pointer
subfunction sends request
subfunction gets answer
subfunction closes old socket
subfunction opens new socket (socket(), setsockopt, bind()) on the location pointed by the socket pointer (thus replacing the original)
- Problem
next call to sendto() fails either with errno 9 (bad file number) or with errno 88 (socket operation on non-socket).
Call to function in main: (servaddr is a struct sockaddr_in, hence the cast; sockfd is an int)
int checkParameters;
checkParameters=clientrequest(&sockfd, (struct sockaddr*) &servaddr, 0, settings);
clientrequest() description:
int clientparameters(int* socketpt, struct sockaddr* remaddr, unsigned int parameters[])
{
unsigned char timeouts = 0;
int received = 0;
socklen_t len;
unsigned char* buff;
if((buff = malloc(MAX_LINE)) == NULL) {
fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);
return -1;
}
unsigned char i;
memset(buff, 0, MAX_LINE);
if(encode(buff, PARAM) < 0) {
fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);
free(buff);
return -1;
}
if(sendto(*socketpt, buff, 1, 0, remaddr, sizeof(struct sockaddr)) < 0) {
fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);
free(buff);
return -1;
}
while(received == 0) {
len = sizeof(struct sockaddr);
if((received = recvfrom(*socketpt, buff, MAX_LINE, 0, remaddr, &len)) < 0) {
if(errno == EWOULDBLOCK) {
if(timeouts == TIMEOUT_NUM) {
fprintf(stderr, "Server non found, process %d, errno %d\n", getpid(), errno);
free(buff);
return -1;
}
received = 0;
timeouts++;
}
else {
fprintf(stderr, "Error occurred, process %d\n errno: %d\n", getpid(), errno);
free(buff);
return -1;
}
}
}
}
memcpy(parameters, uncap(buff), sizeof(unsigned int)*3);
/*"uncap" removes user-level protocol header from payload*/
free(buff);
/*Store old socket port + IP address*/
struct sockaddr_in addr;
len = sizeof(struct sockaddr);
if(getsockname(*socketpt, (struct sockaddr*)&addr, &len) < 0) {
fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);
return -1;
}
if(close(*socketpt) < 0) {
fprintf(stderr,"Errore occurred, process %d, errno %d\n", getpid(), errno);
return -1;
}
/*Opens new socket*/
if(((*socketpt) = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);
return -1;
}
/*Set timer*/
struct timeval t;
t.tv_usec = parameters[2]; //Where timer is set
if(setsockopt(*socketpt, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval)) < 0 ) {
fprintf(stderr, "errno: %d\n win: %u\t loss: %u\t timeout: %u\n\n", errno, parameters[0], parameters[1], parameters[2]);
fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);
if(close(*socketpt) < 0) {
fprintf(stderr, "Errore in close() in clientrequest(), processo %d, errno %d\n", getpid(), errno);
}
return(-1);
}
if(bind(*socketpt, (struct sockaddr*)&addr, sizeof(struct sockaddr)) < 0) {
fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);
if(close(*socketpt) < 0) {
fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);
}
return(-1);
}
return 0;
}
While once I enter a second request function, it fails at the first sendto() with errno 88.
Here's some sandbox code I tried. It basically follows the same socket(), setsockopt(), bind(), sendto(), close() approach, except "sendto" sends to the same IP/port the socket's bound.
int* receptionfd = malloc(4);
struct sockaddr_in addr;
char buff[MAX_LINE];
int n;
unsigned int len;
if((*receptionfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Error occurred\n");
free(receptionfd);
exit(-1);
}
memset((void*)&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
if(inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) <= 0) {
perror("Errore occurred\n");
free(receptionfd);
exit(-1);
}
addr.sin_port = htons(5050);
struct timeval t;
t.tv_usec = 20000;
if(setsockopt(*receptionfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval)) < 0 ) {
fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);
if(close(*receptionfd) < 0) {
fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);
}
return(-1);
}
if(bind(*receptionfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
perror("Error occurred\n");
free(receptionfd);
exit(-1);
}
if(sendto(*receptionfd, buff, 0, 0, (struct sockaddr*)&addr, sizeof(struct sockaddr)) < 0) {
fprintf(stderr, "Error occurred, first sendto(), errno %d\n", errno);
free(receptionfd);
exit(-1);
}
else
printf("First good\n");
close(*receptionfd);
createsock(receptionfd, addr);
if(sendto(*receptionfd, buff, 0, 0, (struct sockaddr*)&addr, sizeof(struct sockaddr)) < 0) {
fprintf(stderr, "Error occurred, second sendto(), errno %d\n", errno);
free(receptionfd);
exit(-1);
}
else {
printf("Second good\n");
}
close(*receptionfd);
free(receptionfd);
exit(0);
createsock() body:
void createsock(int* receptionfd, struct sockaddr_in addr) {
if(((*receptionfd) = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Error occurred\n");
free(receptionfd);
exit(-1);
}
memset((void*)&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
if(inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) <= 0) {
perror("Error occurred\n");
free(receptionfd);
exit(-1);
}
addr.sin_port = htons(5050);
struct timeval t;
t.tv_usec = 20000;
if(setsockopt(*receptionfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval)) < 0 ) {
fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);
if(close(*receptionfd) < 0) {
fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);
}
}
if(bind(*receptionfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
perror("Error occurred\n");
exit(-1);
}
}
(You might notice I copy-pasted a few things from the main sandbox function)
Well, the sandbox always executes "First good, Second good".
I might employ a solution using "select()" and see if it works, but I'd rather understand why this is happening first.

Related

TCP connection fails at recv() function

I'm a newbie in socket programming.
I'm trying to interface in TCP between server and client by following a certain protocol.
After the connection is established, the communication starts by client sending a certain packet to the server. My program fails at the recv() function at client side.
Let me share you the client side of my code:
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
iResult = getaddrinfo(LOCAL_IP, "8081", &hints, &result);
if (iResult != 0)
{
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
{
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET)
{
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
MSG_PDDAU_INFO_PACKET* ps8ptr = new MSG_PDDAU_INFO_PACKET;
memset(ps8bufrecv, 0, DEFAULT_BUFLEN);
s32packetlen = sizeof(MSG_PDDAU_INFO_PACKET);
printf("size %d\n", sizeof(MSG_PDDAU_INFO_PACKET));
iResult = recv(ConnectSocket, ps8bufrecv, s32packetlen, 0);
if (iResult == -1)
{
printf("Here !\n");
fprintf(stderr, "recv Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
memcpy(ps8ptr,ps8bufrecv,sizeof(MSG_PDDAU_INFO_PACKET));
And here is the server side of the code:
nErrorStatus = WSAStartup(wVersionRequested, &wsaData);
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
if(serv_sock == -1)
{
printf( "socket() Error..Error --> Code %d ", WSAGetLastError() );
error_handling("socket error");
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = PF_INET;
serv_addr.sin_addr.s_addr = inet_addr(ip);
serv_addr.sin_port = htons(CLIENT_PORT_NUMBER);
if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
{
printf( "bind() Error..Error --> Code %d ", WSAGetLastError() );
error_handling("bind error");
}
if(listen(serv_sock, 5) == -1)
{
printf( "listen() Error..Error --> Code %d ", WSAGetLastError() );
error_handling("listen error");
}
clnt_addr_size = sizeof(clnt_addr);
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
if(clnt_sock == -1)
{
printf( "accept() Error..Error --> Code %d ", WSAGetLastError() );
error_handling("accept error");
}
MSG_PDDAU_INFO_PACKET* ps8ptr = new MSG_PDDAU_INFO_PACKET;
ps8ptr->header.msg_id = MSG_PDDAU_INFO_ID;
ps8ptr->header.msg_type = MSG_REQUEST_TYPE;
ps8ptr->time_enable = 0x01;
s32packetlen = sizeof(MSG_PDDAU_INFO_PACKET);
memset(ps8bufsend, 0, DEFAULT_BUFLEN);
memcpy(ps8bufsend,ps8ptr, s32packetlen);
iResult = send(clnt_sock, ps8bufsend, s32packetlen, 0);
if (iResult == -1)
{
fprintf(stderr, "send Error Occurred %s (%d)\n", strerror(errno), errno);
return -1;
}
The code keeps failing at the first recv/send interface after the connection, and the error message looks like below.
Server side:
Time msg id : 5
Time setting failed
Client side:
recv Error Occurred Invalid argument (22)
I don't know what's the correct way to communicate in my case.
It'd be great if anyone can point out my problem here.

Using select with multiple sockets

I am using lwip with one thread (based on FreeRTOS, where I only want one task). There, I have 2 sockets listening for incoming connections. Therefore, I want to use select to wait for incoming new connections and also I don't want to block while waiting. Therefore, after creating both sockets, binding and listening I go to my infinitive loop:
#define TOTAL_MASTERS 2
fd_set current_sockets, ready_sockets;
struct timeval timeout;,
int master1_fd, master2_fd;
struct sockaddr_in address;
// Master 1
if ((master1_fd = lwip_socket(AF_INET, SOCK_STREAM, 0)) < 0) {
xil_printf("TCP server: Error creating Socket\r\n");
return;
}
// Set up to wait for subscribers
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port1);
address.sin_addr.s_addr = INADDR_ANY;
if (n=bind(master1_fd, (struct sockaddr *)&address, sizeof (address)) < 0) {
port = port11;
xil_printf("[err: %d] TCP server: Unable to bind to port %d\r\n",n, ((port&0xFF)<<8) | ((port>>8)&0xFF));
close(sock);
return;
}
if (n=listen(master1_fd, 1) < 0) {
xil_printf("[err: %d] TCP server: tcp_listen failed\r\n", n);
close(master1_fd);
return;
}
// Master 2
if ((master2_fd = lwip_socket(AF_INET, SOCK_STREAM, 0)) < 0) {
xil_printf("TCP server: Error creating Socket\r\n");
return;
}
// Set up to wait for subscribers
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port2);
address.sin_addr.s_addr = INADDR_ANY;
if (n=bind(master2_fd, (struct sockaddr *)&address, sizeof (address)) < 0) {
port = port22;
xil_printf("[err: %d] TCP server: Unable to bind to port %d\r\n",n, ((port&0xFF)<<8) | ((port>>8)&0xFF));
close(sock);
return;
}
if (n=listen(master2_fd, 1) < 0) {
xil_printf("[err: %d] TCP server: tcp_listen failed\r\n", n);
close(master2_fd);
return;
}
FD_ZERO(&current_sockets);
FD_SET(master1_fd, &current_sockets);
FD_SET(master2_fd, &current_sockets);
timeout.tv_sec = 0;
timeout.tv_usec = 5000; // 5ms for timeout
while(1)
{
FD_ZERO(&ready_sockets);
ready_sockets = current_sockets;
if(sret = select(TOTAL_PUBLISHERS, &current_sockets, NULL, NULL, &timeout) == 0)
{
//timeout
//xil_printf("Select time out: %d\n", sret);
}
else
{
xil_printf("Something happened: %d\n", sret);
for(int i=0; i<TOTAL_MASTERS; i++){
if(FD_ISSET(i, &ready_sockets)){
if(i == publisher_FPGA_ROS_mymsg.socket_to_wait_for_subscribers_fd){
if ((new_sd = lwip_accept(master1_fd, (struct sockaddr *)&remote, (socklen_t *)&size)) > 0){
if ((read_bytes = lwip_recvfrom(new_sd, message, ARR_SIZE, 0, NULL, NULL)) > 0) {
xil_printf("New client on master 1:\n%s", message);
}
}
}
if(i == publisher_FPGA_ROS_geometry_msgs_point.socket_to_wait_for_subscribers_fd){
if ((new_sd = lwip_accept(master2_fd, (struct sockaddr *)&remote, (socklen_t *)&size)) > 0){
if ((read_bytes = lwip_recvfrom(new_sd, message, ARR_SIZE, 0, NULL, NULL)) > 0) {
xil_printf("New client on master 2:\n%s", message);
}
}
}
}
}
}
}
The problem that I have is that with a timeout it does not react to incoming new clients but always times out. If I change &timeout in selectto NULL, then I get incoming connections but only on master1.
Is it possible to wait for incoming connections on more than one socket using only one thread or task?
Thanks for the help.
There are a number of mistakes in your code.
You are mixing lwip and C socket functions. Use only lwip functions for consistency.
Your bind(), listen(), and select() expressions are missing required parenthesis, since < and == have a higher precedence than =. You are using parenthesis correctly on the lwip_socket(), lwip_accept() and lwip_recvfrom() expressions, though. But really, it is generally considered bad practice to perform assignment and comparison in the same expression, you really should break those up into separate expressions.
You are passing the wrong max descriptor value to the 1st parameter of select(). It needs to be +1 more than the highest socket descriptor you are select()'ing.
You are passing your master list current_sockets to the 2nd parameter of select() instead of passing your ready_sockets copy. So current_sockets is being modified and may not contain all of the listening sockets anymore on the next call to select(). After a few calls, it is likely to end up completely empty.
Your FD_ISSET() check is wrong, too. You are checking file descriptors 0 and 1, which are not the listening sockets you created. You don't need the for loop to check master1_fd and master2_fd, you can pass them as-is to FD_ISSET().
With that said, try this instead:
fd_set current_sockets, ready_sockets;
struct timeval timeout;,
int master1_fd, master2_fd;
struct sockaddr_in address, remote;
socklen_t size;
// Master 1
master1_fd = lwip_socket(AF_INET, SOCK_STREAM, 0);
if (master1_fd < 0) {
xil_printf("[err: %d] TCP server: Error creating Socket\r\n", errno);
return;
}
// Set up to wait for subscribers
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port1);
address.sin_addr.s_addr = INADDR_ANY;
n = lwip_bind(master1_fd, (struct sockaddr *)&address, sizeof (address));
if (n < 0) {
xil_printf("[err: %d] TCP server: Unable to bind to port %hd\r\n", errno, port1);
lwip_close(master1_fd);
return;
}
n = lwip_listen(master1_fd, 1);
if (n < 0) {
xil_printf("[err: %d] TCP server: tcp_listen failed\r\n", errno);
lwip_close(master1_fd);
return;
}
// Master 2
master2_fd = lwip_socket(AF_INET, SOCK_STREAM, 0);
if (master2_fd < 0) {
xil_printf("[err: %d] TCP server: Error creating Socket\r\n", errno);
lwip_close(master1_fd);
return;
}
// Set up to wait for subscribers
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port2);
address.sin_addr.s_addr = INADDR_ANY;
n = lwip_bind(master2_fd, (struct sockaddr *)&address, sizeof (address));
if (n < 0) {
xil_printf("[err: %d] TCP server: Unable to bind to port %hd\r\n", errno, port2);
lwip_close(master2_fd);
lwip_close(master1_fd);
return;
}
n = lwip_listen(master2_fd, 1);
if (n < 0) {
xil_printf("[err: %d] TCP server: tcp_listen failed\r\n", errno);
lwip_close(master2_fd);
lwip_close(master1_fd);
return;
}
FD_ZERO(&current_sockets);
FD_SET(master1_fd, &current_sockets);
FD_SET(master2_fd, &current_sockets);
int max_fd;
if (master1_fd > master2_fd)
max_fd = master1_fd;
else
max_fd = master2_fd;
while (1)
{
FD_ZERO(&ready_sockets);
ready_sockets = current_sockets;
timeout.tv_sec = 0;
timeout.tv_usec = 5000; // 5ms for timeout
sret = lwip_select(max_fd+1, &ready_sockets, NULL, NULL, &timeout);
if (sret < 0)
{
//error
//xil_printf("Select error: %d\n", errno);
}
else if (sret == 0)
{
//timeout
//xil_printf("Select time out\n");
}
else
{
xil_printf("Something happened\n");
if (FD_ISSET(master1_fd, &ready_sockets)){
size = sizeof (remote);
new_sd = lwip_accept(master1_fd, (struct sockaddr *)&remote, &size)
if (new_sd > 0){
read_bytes = lwip_recv(new_sd, message, ARR_SIZE, 0);
if (read_bytes > 0) {
xil_printf("New client on master 1:\n%.*s", read_bytes, message);
}
}
}
if (FD_ISSET(master2_fd, &ready_sockets)){
size = sizeof (remote);
new_sd = lwip_accept(master2_fd, (struct sockaddr *)&remote, &size);
if (new_sd > 0){
read_bytes = lwip_recv(new_sd, message, ARR_SIZE, 0);
if (read_bytes > 0) {
xil_printf("New client on master 2:\n%.*s", read_bytes, message);
}
}
}
}
}
However, you still have a big logic hole in your code. You are leaking client sockets, as you never close() the socket descriptors that lwip_accept() returns. And you need to select() the accepted sockets to know when they have data available to be read.
So try something more like this instead:
fd_set ready_sockets;
struct timeval timeout;
int master1_fd, master2_fd, max_fd, curr_fd, i;
int[] sockets; // <-- PSEUDO-CODE!!
struct sockaddr_in address, remote;
socklen_t size;
// Master 1
master1_fd = lwip_socket(AF_INET, SOCK_STREAM, 0);
if (master1_fd < 0) {
xil_printf("[err: %d] TCP server: Error creating Socket\r\n", errno);
return;
}
// Set up to wait for subscribers
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port1);
address.sin_addr.s_addr = INADDR_ANY;
n = lwip_bind(master1_fd, (struct sockaddr *)&address, sizeof (address));
if (n < 0) {
xil_printf("[err: %d] TCP server: Unable to bind to port %hd\r\n", errno, port1);
lwip_close(master1_fd);
return;
}
n = lwip_listen(master1_fd, 1);
if (n < 0) {
xil_printf("[err: %d] TCP server: tcp_listen failed\r\n", errno);
lwip_close(master1_fd);
return;
}
// Master 2
master2_fd = lwip_socket(AF_INET, SOCK_STREAM, 0);
if (master2_fd < 0) {
xil_printf("[err: %d] TCP server: Error creating Socket\r\n", errno);
lwip_close(master1_fd);
return;
}
// Set up to wait for subscribers
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port2);
address.sin_addr.s_addr = INADDR_ANY;
n = lwip_bind(master2_fd, (struct sockaddr *)&address, sizeof (address));
if (n < 0) {
xil_printf("[err: %d] TCP server: Unable to bind to port %hd\r\n", errno, port2);
lwip_close(master2_fd);
lwip_close(master1_fd);
return;
}
n = lwip_listen(master2_fd, 1);
if (n < 0) {
xil_printf("[err: %d] TCP server: tcp_listen failed\r\n", errno);
lwip_close(master2_fd);
lwip_close(master1_fd);
return;
}
sockets.add(master1_fd); // <-- PSEUDO-CODE!!!
sockets.add(master2_fd); // <-- PSEUDO-CODE!!!
while (1)
{
max_fd = -1;
for (int i = 0; i < sockets.length; ++i){ // <-- PSEUDO-CODE!!!
curr_fd = sockets[i];
FD_SET(curr_fd, &ready_sockets);
if (curr_fd > max_fd){
max_fd = curr_fd;
}
}
timeout.tv_sec = 0;
timeout.tv_usec = 5000; // 5ms for timeout
sret = lwip_select(max_fd+1, &ready_sockets, NULL, NULL, &timeout);
if (sret < 0)
{
//error
//xil_printf("Select error: %d\n", errno);
}
else if (sret == 0)
{
//timeout
//xil_printf("Select time out\n");
}
else
{
xil_printf("Something happened\n");
i = 0;
while (i < sockets.length){ // <-- PSEUDO-CODE!!!
curr_fd = sockets[i];
if (FD_ISSET(curr_fd, &ready_sockets)){
if ((curr_fd == master1_fd) || (curr_fd == master2_fd)){
size = sizeof (remote);
new_sd = lwip_accept(curr_fd, (struct sockaddr *)&remote, &size)
if (new_sd > 0){
xil_printf("New client on master %d:\n", (curr_fd == master1_fd) ? 1 : 2);
sockets.add(new_sd); // <-- PSEUDO-CODE!!!
}
}
else{
read_bytes = lwip_recv(curr_fd, message, ARR_SIZE, 0);
if (read_bytes > 0) {
xil_printf("%.*s", read_bytes, message);
}
else {
lwip_close(curr_fd);
sockets.remove(i); // <-- PSEUDO-CODE!!!
continue;
}
}
}
++i;
}
}
}
for(i = 0; i < sockets.length; ++i){ // <-- PSEUDO-CODE!!!
lwip_close(sockets[i]);
}
Regarding the PSEUDO-CODE portions of the above code, you did not indicate whether you are using C or C++. In C++, you could simple use a std::vector for the sockets list. But in C, you would have to decide whether you want to use a fixed array with a max capacity or use a dynamically sized array. I didn't really feel like writing a bunch of extra code to manage the list. I leave that as an exercise for you to figure out. How you store the sockets outside of the fd_set being select()'ed is not important to this topic.

bind() return EINVAL

This is the code snippet (from beejus) where I am trying to create a process which will create a thread which will act as a Unix Domain Socket Server.
void *domain_socket_cepki_server() {
s = socket(AF_UNIX, SOCK_STREAM, 0);
fprintf(stderr, "socket val is : %d\n", s);
if (s == -1) {
perror("socket");
fprintf(stderr, "SOCKET ERROR: %d\n", s);
}
memset(&local, 0, sizeof(struct sockaddr_un));
local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH);
unlink(local.sun_path);
//len = strlen(local.sun_path) + sizeof(local.sun_family);
rc = bind(s, (struct sockaddr *) &local, sizeof(local));
if (rc == -1) {
perror("bind");
fprintf(stderr, "bind failed %d : %s", errno, strerror(errno));
exit(1);
}
if (listen(s, 5) == -1) {
perror("listen");
fprintf(stderr, "listen failed : %s", strerror(errno));
exit(1);
}
int done, n;
printf("Waiting for a connection...\n");
t = sizeof(remote);
if ((s2 = accept(s, (struct sockaddr *)&remote, &t)) == -1) {
perror("accept");
exit(1);
}
// send and recv code further.
}
With this I am getting following error:
bind: Invalid argument
bind() EINVAL says the following:
EINVAL The socket is already bound to an address.
EINVAL addrlen is wrong, or addr is not a valid address for this
socket's domain.
What can go wrong in this bind() system call ?

Winsock non-blocking overlapped IO still blocks

I am trying to write a simple winsock client that sends data to a
winsock server using non-blocking overlapped IO. The problem is that the WSASend call is blocking. The client code looks like this
// Initialize Winsock
WSAStartup(MAKEWORD(2, 2), &wsaData);
// Create a SOCKET for connecting to server
ConnectSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
// Connect to server.
WSAConnect(ConnectSocket, ai_addr, ai_addrlen, 0, 0, 0, 0);
// Make the socket non-blocking
u_long iMode = 1;
ioctlsocket(ConnectSocket, FIONBIO, &iMode);
// Send the data
WSAOVERLAPPED SendOverlapped{};
SendOverlapped.hEvent = WSACreateEvent();
WSASend(ConnectSocket, &DataBuf, 1, &SendBytes, 0, &SendOverlapped, 0);
I have made the socket non-blocking through the ioctlsocket function and I have provided WSA_FLAG_OVERLAPPED flag to the WSASocket function. I have also provided the lpOverlapped parameter to the WSASend function. However, the call to WSASend is still blocking. Am I missing something here?
Please excuse the lack of error checking in the above code, it is only to keep it simple for the purposes of this question.
Clarification: The reason why it seems to me the call is blocking is this - I called the WSASend function 2560 times in a loop, sending 4MB each time in the loop. The loop completed in 16 secs after all the data was transferred to the server. If it was non-blocking, I would have expected the loop to complete much sooner. As expected, the WSASend function does return with ERROR_IO_PENDING though.
Here is the full client code
// Client.cpp
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#include <ctime>
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define DEFAULT_BUFLEN 4 * 1024 * 1024
#define DEFAULT_PORT "27015"
int __cdecl main(int argc, char **argv)
{
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
// Resolve the server address and port
addrinfo *result = NULL;
addrinfo hints{};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
iResult = getaddrinfo("127.0.0.1", DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
SOCKET ConnectSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = WSAConnect(ConnectSocket, result->ai_addr, result->ai_addrlen, 0, 0, 0, 0);
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
// Make the socket non-blocking
u_long iMode = 1;
iResult = ioctlsocket(ConnectSocket, FIONBIO, &iMode);
if (iResult != NO_ERROR) {
printf("ioctlsocket failed with error: %ld\n", iResult);
WSACleanup();
return 1;
}
// Prepare the buffer
char *sendbuf = new char[DEFAULT_BUFLEN];
for (int i = 0; i < DEFAULT_BUFLEN; ++i)
sendbuf[i] = 'a';
WSABUF DataBuf;
DWORD SendBytes = 0;
DataBuf.buf = sendbuf;
DataBuf.len = DEFAULT_BUFLEN;
// Send the buffer in a loop
int loopCount = 2560;
WSAOVERLAPPED* SendOverlapped = (WSAOVERLAPPED*)calloc(loopCount, sizeof(WSAOVERLAPPED));
clock_t start = clock();
for (int i = 0; i < loopCount; ++i)
{
SendOverlapped[i].hEvent = WSACreateEvent();
iResult = WSASend(ConnectSocket, &DataBuf, 1, &SendBytes, 0, SendOverlapped + i, 0);
if (iResult == SOCKET_ERROR)
{
if (ERROR_IO_PENDING == WSAGetLastError())
{
continue;
}
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
}
std::cout << "initiating send data took " << clock() - start << " ms" << std::endl;
// Wait for all the events to be signalled
for (int i = 0; i < loopCount; ++i)
{
iResult = WSAWaitForMultipleEvents(1, &SendOverlapped[i].hEvent, TRUE, INFINITE, TRUE);
if (iResult == WSA_WAIT_FAILED) {
printf("WSAWaitForMultipleEvents failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
DWORD Flags = 0;
BOOL result = WSAGetOverlappedResult(ConnectSocket, SendOverlapped + i, &SendBytes, FALSE, &Flags);
if (result == FALSE) {
printf("WSASend failed with error: %d\n", WSAGetLastError());
break;
}
}
std::cout << "actual send data took " << clock() - start << " ms";
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ConnectSocket);
WSACleanup();
////free(SendOverlapped);
return 0;
}
And here is the server side code
// Server.cpp
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 4 * 1024 * 1024
#define DEFAULT_PORT "27015"
int __cdecl main(void)
{
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
// Resolve the server address and port
addrinfo hints{};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
addrinfo *result = NULL;
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
SOCKET ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// Accept a client socket
SOCKET ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// No longer need server socket
closesocket(ListenSocket);
// Receive until the peer shuts down the connection
char* recvbuf = new char[DEFAULT_BUFLEN];
do {
iResult = recv(ClientSocket, recvbuf, DEFAULT_BUFLEN, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
}
else if (iResult == 0)
printf("Connection closing...\n");
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} while (iResult > 0);
// shutdown the connection since we're done
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
return 0;
}
The WSASend call was blocking because it was completing too quickly. One would think a 4MB transfer would be sufficiently large to call for async processing but that was not the case. When I inserted a sleep of 1 ms on the server side, I could see the client processing asynchronously, and the loop ended much before the data transfer.

Bind failed with Invalid argument error

I'm trying to write a simple program which uses bind. The code compiles on solaris, but I get a bind() failed with Invalid Argument error.
I have tried many times but getting the same error, I'm unable to figure out the error.
Here is the code :
int my_func ()
{
struct sockaddr_storage name;
struct addrinfo hints, *res;
int status;
char hostnamestr[256];
gethostname (hostnamestr, 256);
int iRC;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((status = getaddrinfo(hostnamestr, NULL, &hints, &res) != 0))
{
printf("getaddrinfo: %s\n", gai_strerror(status));
return 1;
}
memcpy(&name, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
monsocket = socket (name.ss_family, SOCK_STREAM, IPPROTO_TCP);
int iLastError = WSAGetLastError ();
if (monsocket == -1)
{
fprintf (stderr, "cannot open socket for monitors [%s]\n", wsaerror (iLastError));
return 1;
}
sockopts(monsocket);
int flags;
flags = fcntl (monsocket, F_GETFL);
iLastError = WSAGetLastError ();
if (flags < 0)
{
fprintf (stderr, "cannot get flags for socket [%s]\n", wsaerror (iLastError));
return 1;
}
iRC = fcntl (monsocket, F_SETFL, flags | O_NONBLOCK);
iLastError = WSAGetLastError ();
if (iRC == -1)
{
fprintf (stderr, "cannot set flags for socket [%s]\n", wsaerror (iLastError));
return 1;
}
int iPort;
if(name.ss_family == AF_INET)
{
((struct sockaddr_in *) &name)->sin_port = htons (8091);
}
else if(name.ss_family == AF_INET6)
{
((struct sockaddr_in6 *) &name)->sin6_port = htons (8091);
}
struct sockaddr_in* ipv = (struct sockaddr_in *) &name;
printf("connecting to addr: %s\n", inet_ntoa(ipv->sin_addr));
iRC = bind (monsocket, (struct sockaddr *) &name, sizeof (name));
iLastError = WSAGetLastError ();
if (iRC == -1)
{
close(monsocket);
monsocket=-1;
fprintf (stderr, "could not bind to port %d\n", iPort);
printf("Error %s",wsaerror (iLastError));
return 1;
}
else
{
fprintf (SCHED_SHOW_MSG, "bound on port %i\n", ntohs (iPort));
}
iRC = listen (monsocket, SOMAXCONN);
iLastError = WSAGetLastError ();
if (iRC == -1)
{
fprintf (stderr, "could not listen to socket [%s]\n", wsaerror (iLastError));
return 1;
}
return 0;
}
bind (monsocket, (struct sockaddr *) &name, sizeof (name))
Your sizeof(name) yields the size of the generic sockaddr_storage size. You need the size of sockaddr_in or sockaddr_in6.
In any case, you'd be better of by just using the stuff from getaddrinfo directly:
monsocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
bind(monsocket, res->ai_addr, res->ai_addrlen);
In order to do that you'll have to move your freeaddrinfo(res) call.
i got same error. and later found that i created socket for AF_INET and was trying to bind using IPv6 address.