Hi I am newly to socket programing and I want to create possix tcp client and server , which handle keep alive and client to be able to wait for response with timeout. I read about socket options SO_KEEPALIVE and SO_RCVTIMEO and I have try to set the client socket with both of them .Why get Resource temporarily unavailable now? This is my client code :
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define INDEX_ZERO (0)
struct sockaddr_in client;
socklen_t clientsz = sizeof(client);
int client_socket = -1;
int port = 5900;
const char* ip = "127.0.0.1";
bool socket_created = false;
bool already_connect_to_server = false;
bool SocketCreate()
{
if((client_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Socket()");
return false;
}
else
{
return true;
}
}
void ConnectToServer(void)
{
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip);
struct timeval tv;
tv.tv_sec = 2;
tv.tv_usec = 500000;
setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv));
while ((connect(client_socket, (struct sockaddr *)&server, sizeof(server)) < 0))
{
perror("Connect()");
sleep(1);
}
int enableKeepAlive = 1;
int count = 3;
int maxIdle = 1;
int interval = 1;
setsockopt(client_socket, SOL_SOCKET, SO_KEEPALIVE, &enableKeepAlive, sizeof(enableKeepAlive));
setsockopt(client_socket, IPPROTO_TCP, TCP_KEEPIDLE, &maxIdle, sizeof(maxIdle));
setsockopt(client_socket, IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof(count));
setsockopt(client_socket, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval));
getsockname(client_socket, (struct sockaddr *) &client, &clientsz);
printf("[%s:%u] > ", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
}
uint8_t SendTcpPacket(uint8_t *payload, size_t len)
{
bool sended = false;
uint8_t ret_val;
if(! socket_created)
{
socket_created = SocketCreate();
if(! socket_created)
{
return 201;
}
}
if(! already_connect_to_server)
{
already_connect_to_server = true;
ConnectToServer();
}
while (!sended)
{
uint8_t one = 1;
if (client_socket > 0)
{
if (send(client_socket, payload, len, 0) < 0)
{
perror("Send()");
}
else
{
printf("Sended %uhh",payload[0]);
}
ssize_t recv_ret = recv(client_socket, payload, len, 0);
if ((recv_ret > 1) || (recv_ret < 0) || (recv_ret == EAGAIN) || (recv_ret == EWOULDBLOCK))
{
printf("Recv() failed with value: , %ld \n", recv_ret);
perror("Recv():\n");
if (recv_ret < 0)
{
ret_val = 101;
}
else
{
ret_val = 255;
}
}
else
{
printf("Received %lu bytes from the server...\n", recv_ret);
for (int i = 0; i < 1; i++)
printf("<--- buff[%d] = %hhu value\n", i, payload[i]);
}
ret_val = payload[INDEX_ZERO];
sended = true;
}
}
return ret_val;
}
int main(void)
{
uint8_t payload[2] = {0,1};
size_t len = sizeof(payload);
int counter =0;
while(true)
{
counter++;
if(counter % 2 == 0)
{
payload[0] = 1;
}
else
{
payload[0] = 0;
}
if(counter > 60000)
{
counter = 0;
}
SendTcpPacket(payload, len);
}
close(client_socket);
return 0;
}
And this is my server code:
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <iostream>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
using namespace std;
#define BUFFER_SIZE ( 2 ) // Buffer Size
#define CMD_RESET_CHAIN (uint8_t)0x00
#define CMD_INIT_CHAIN (uint8_t)0x01
#define CMD_DEACTIVATE_ALL (uint8_t)0x10
#define CMD_ACTIVATE_ALL (uint8_t)0x11
#define CMD_DEACTIVATE_OUT (uint8_t)0x20
#define CMD_ACTIVATE_OUT (uint8_t)0x21
#define CMD_GET_FEEDBACK (uint8_t)0x30
#define POSITIVE_RESPONSE (uint8_t)0x00
#define NEGATIVE_RESPONSE (uint8_t)0x80
int s;
int ns;
int enableKeepAlive = 1;
int count = 3;
int maxIdle = 1;
int interval = 1;
socklen_t sizeof_maxIdle = sizeof(maxIdle);
uint8_t buf[BUFFER_SIZE];
struct sockaddr_in client;
struct sockaddr_in server;
socklen_t namelen;
bool already_bind = false;
int test_counter = 0;
void socket_cr_bind_listen(int port)
{
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Socket()");
exit(2);
}
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
if (bind(s, (struct sockaddr *)&server, sizeof(server)) < 0)
{
perror("Bind()");
exit(3);
}
if (listen(s, 1) != 0)
{
perror("Listen()");
exit(4);
}
else
{
printf("Server listening on port: %d...\n",ntohs(server.sin_port));
}
}
int RunStandardTcpServer(const char* ip, int port, int res_mock)
{
if(! already_bind)
{
socket_cr_bind_listen(port);
already_bind = true;
}
namelen = sizeof(client);
uint8_t payload = 0;
test_counter++;
while ((ns = accept(s, (struct sockaddr *)&client, &namelen)) > 0)
{
setsockopt(ns, SOL_SOCKET, SO_KEEPALIVE, &enableKeepAlive, sizeof(enableKeepAlive));
setsockopt(ns, IPPROTO_TCP, TCP_KEEPIDLE, &maxIdle, sizeof(maxIdle));
setsockopt(ns, IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof(count));
setsockopt(ns, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval));
ssize_t bytes_read = recv(ns, buf, sizeof(BUFFER_SIZE), 0);
if(test_counter % 2 == 0)
{
}
if(test_counter > 65000)
{
test_counter = 0;
}
if ( bytes_read == -1)
{
perror("Recv()");
exit(6);
}
printf("Read bytes: %ld\n", bytes_read);
cout<<"Byte of interest"<<(unsigned)buf[0]<<endl;
cout<<"If expceted second byte is: "<<(unsigned)buf[1]<<endl;
switch (res_mock)
{
case 0:
{
payload = POSITIVE_RESPONSE;
cout<<"Simulating positive response"<<endl;
break;
}
case 1:
{
payload = NEGATIVE_RESPONSE;
cout<<"Simulating negative response"<<endl;
break;
}
case 2:
cout<<"Simulating unknown response"<<endl;
payload = 222;
break;
case 3:
{
int i = 0;
cout<<"Simulating late response"<<endl;
while(i<5)
{
sleep(1);
i++;
}
}
case 4:
{
cout<<"Simulating no response"<<endl;
while(true)
{
sleep(5);
}
}
default:
break;
}
if (send(ns, &payload, 1, 0) < 0)
{
perror("Send()");
exit(7);
}
memset(buf,255,sizeof(BUFFER_SIZE));
}
if (ns == -1)
{
perror("Accept()");
exit(5);
}
printf("After accept server listening at port: %d...\n",ntohs(server.sin_port));
return 0;
}
int main(int argc, char* argv[])
{
if(argc <= 3)
{
printf("usage: ip_address + port_number + response mock (0-positive 1-negative 2-unknown response 3-no response )\n");
return -1;
}
const char* ip = argv[1];
int port = atoi(argv[2]);
int res_mock = atoi(argv[3]);
while(true)
{
RunStandardTcpServer(ip, port,res_mock);
if(getsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &maxIdle, &sizeof_maxIdle) < 0) {
perror("getsockopt()");
close(s);
exit(EXIT_FAILURE);
}
}
close(ns);
close(s);
}
What I have tried:
-I have tried first to implement the timeout option and it was working , but only when I reconnect every time with new socket and file descriptor respectively.
-I also tried only the keep alive part but there was no keep alive (when I turn off the server, the client says: Connection shutdown by peer).
-I have used wireshark to check the payloads out and in , and there was keepalive payload, but not the effect which I expected, as I mention above.
Thank you for the attention!