I'm trying to create a simple proxy server using BSD sockets, which listens on a port for a request and then passes that request on to another server, before sending the server's response back to the browser.
I am able to receive a REST request from the browser, using the code below:
void *buffer = malloc(512);
long length = 0;
while (1) {
void *tempBuffer = malloc(512);
long response = recv(acceptedDescriptor, tempBuffer, 512, 0);
if (response == 0 || response < 512) {
free(tempBuffer);
printf("Read %lu bytes\n", length);
break;
}
memcpy(buffer + length, tempBuffer, response);
free(tempBuffer);
length += response;
realloc(buffer, length + 512);
}
However, recv() should return 0 when the connection is closed by the peer (in this case the browser), but this is never the case. The only way I am able to detect whether or not the connection has closed is by checking if the response is less than the maximum amount requested from recv(), 512 bytes. This is sometimes problematic as some requests I see are incomplete.
If there is no more data to receive, recv() blocks and never returns, and setting the accepted descriptor to be non-blocking means that the read loop goes on forever, never exiting.
If I:
Set the listening socket descriptor to non-blocking, I get a EAGAIN error (resource temporarily unavailable) when I try to accept() the connection
Set the accepted socket descriptor to non-blocking, recv() never returns 0 and the loop continues on forever
Set them both to non-blocking, I get a 'bad file descriptor' error when trying to accept() the connection
Don't set either of them to non-blocking, the loop never exits because recv() never returns.
The socket itself is created as follows, but since it is able to detect a request, I can't see anything wrong with its initialisation:
int globalDescriptor = -1;
struct sockaddr_in localServerAddress;
...
int initSocket() {
globalDescriptor = socket(AF_INET, SOCK_STREAM, 0);
if (globalDescriptor < 0) {
perror("Socket Creation Error");
return 0;
}
localServerAddress.sin_family = AF_INET;
localServerAddress.sin_addr.s_addr = INADDR_ANY;
localServerAddress.sin_port = htons(8374);
memset(localServerAddress.sin_zero, 0, 8);
int res = 0;
setsockopt(globalDescriptor, SOL_SOCKET, SO_REUSEADDR, &res, sizeof(res));
//fcntl(globalDescriptor, F_SETFL, O_NONBLOCK);
return 1;
}
...
void startListening() {
int bindResult = bind(globalDescriptor, (struct sockaddr *)&localServerAddress, sizeof(localServerAddress));
if (bindResult < 0) {
close(globalDescriptor);
globalDescriptor = 0;
perror("Socket Bind Error");
exit(1);
}
listen(globalDescriptor, 1);
struct sockaddr_in clientAddress;
int clientAddressLength = sizeof(clientAddress);
while (1) {
memset(&clientAddress, 0, sizeof(clientAddress));
clientAddressLength = sizeof(clientAddress);
int acceptedDescriptor = accept(globalDescriptor, (struct sockaddr *)&clientAddress, (socklen_t *)&clientAddressLength);
//fcntl(acceptedDescriptor, F_SETFL, O_NONBLOCK);
if (acceptedDescriptor < 0) {
perror("Incoming Connection Error");
exit(1);
}
void *buffer = malloc(512);
long length = 0;
while (1) {
void *tempBuffer = malloc(512);
long response = recv(acceptedDescriptor, tempBuffer, 512, 0);
if (response == 0) {
free(tempBuffer);
printf("Read %lu bytes\n", length);
break;
}
memcpy(buffer + length, tempBuffer, response);
free(tempBuffer);
length += response;
realloc(buffer, length + 512);
}
executeRequest(buffer, length, acceptedDescriptor);
close(acceptedDescriptor);
free(buffer);
}
}
...
The startListening() function is called only if initSocket() returns 1:
int main(int argc, const char *argv[]) {
if (initSocket() == 1) {
startListening();
}
return 0;
}
I'm probably doing something stupid here, but I'd appreciate any information you may have about this problem and how I could fix it.
Since your REST request is a HTTP method, it has the well-defined HTTP Message Length, so you just have to recv() until the complete message has arrived.
Related
I'm using WinSock2.h to receive data from a TCP socket. Here's the the code for creating the socket and receiving from it:
int Socket_Init(SOCKET * pSocket) {
struct addrinfo lHints;
struct addrinfo *lResult = nullptr;
memset(&lHints, 0, sizeof(lHints));
lHints.ai_family = AF_INET;
lHints.ai_socktype = SOCK_STREAM;
lHints.ai_protocol = IPPROTO_TCP;
if (getaddrinfo(ADDR, PORT_ID, &lHints, &lResult) != 0) {
return -1;
}
*pSocket = socket(lResult->ai_family, lResult->ai_socktype, lResult->ai_protocol);
if (*pSocket == INVALID_SOCKET) {
return -2;
}
// Set receive timeout.
uint32_t timeout = 10000;
if (setsockopt(*pSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) == SOCKET_ERROR) {
return -3;
}
// Set send timeout.
if (setsockopt(*pSocket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) == SOCKET_ERROR) {
return -4;
}
if (connect(*pSocket, lResult->ai_addr, (int)lResult->ai_addrlen) == SOCKET_ERROR) {
return -5;
}
return 0;
}
int Socket_Receive(char * buf, int len, SOCKET * pSocket) {
if (*pSocket == INVALID_SOCKET) {
return -1;
}
int nBytesReceived = recv(*pSocket, buf, len, MSG_WAITALL);
if (nBytesReceived == 0) {
return -2;
} else if (nBytesReceived == SOCKET_ERROR) {
if (WSAECONNABORTED == LAST_ERROR || WSAECONNRESET == LAST_ERROR) {
return -3;
} else {
return -4;
}
}
return nBytesReceived;
}
I use this code to receive packets of 131130 bytes. Using Wireshark, I can see that the incomplete packet happens when there is a retransmission on the last or second-to-last segmented packet (the stack splits the message into chunks of 1460 bytes + header). When this happens, recv() returns (131130 - size retransmitted) instead of 131130. If I do another read for the number of bytes missing, I can get them without problem.
My confusion comes from the fact that I'm using the MSG_WAITALL flag, which doesn't seem to work fully. From the documentation, recv() with the MSG_WAITALL flag will return only if:
The buffer supplied by the caller is completely full.
The connection has been closed.
The request has been canceled or an error occurred.
But I receive no error, the connection is still open, and the buffer isn't full.
I saw this thread, where the replyer says that MSG_WAITALL is not supported by TCP sockets and to use 0 instead of MSG_WAITALL. I tried it, but this resulted in even more retries from my code. Moreover, if it was not supported, then I believe the recv() function should fail immediately with WSAEOPNOTSUPP, which it doesn't.
Am I missing something?
I coded a UDP socket client-server in C. The client sent a query to the server each second for a long time (e.g.: 1 week).
My code ran fine, but I can see in the timeline that the ram increased considerably, at around 14 hours the memory increased to 150M approximately.
The increment is in the client side, the server is working fine.
I need to detect what causes this problem because the program will be running for long time.
What's wrong in my code?
This is my code in the client side:
int consultar_servidor(char *t1_str_)
{
struct timeval t_ini, t_fin, tv;
double secs;
char cadena_enviada[67];
char cadena_recibida[67];
char tx_str[51]= "|0000000000000000|0000000000000000|0000000000000000";
int validacion, i;
long long int t4;
char t4_str[20];
char t2_str_rec[20];
char t2_pps_str_rec[20];
char t3_str_rec[20];
int nBytes, numfd;
if (t1_str_ != 0)
{
strcpy(cadena_enviada,t1_str_);
strcat(cadena_enviada,tx_str);
}
else
{
error("Error recepcion t1");
return 1;
}
if (cont_parametros == 0)
{
set_param();
}
if ( connect( clientSocket, ( struct sockaddr * ) &serverAddr, sizeof( serverAddr) ) < 0 )
error( "Error connecting socket" );
if ( sendto(clientSocket,cadena_enviada,sizeof(cadena_enviada),0,(struct sockaddr *)&serverAddr,addr_size) < 0)
{
close(clientSocket);
error( "Error sentto function");
cont_parametros = 0;
return 1;
}
/** Socket nonblock **/
int flags = fcntl(clientSocket, F_GETFL, 0);
fcntl(clientSocket, F_SETFL, flags | O_NONBLOCK);
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(clientSocket, &readfds);
numfd = clientSocket + 1;
/** Set 700us to receive **/
tv.tv_sec=0;
tv.tv_usec=700000;
/** Server send me **/
int recibo = select(numfd, &readfds,NULL,NULL,&tv);
switch (recibo)
{
case -1:
/** Error reception **/
error("Error reception");
FD_CLR(clientSocket, &readfds);
close(clientSocket);
cont_parametros=0;
return 1;
case 0:
/** Timeout and close socket **/
error( "Error timeout" );
FD_CLR(clientSocket, &readfds);
close(clientSocket);
cont_parametros = 0;
return 1;
default:
/** If socket contain data **/
if (FD_ISSET(clientSocket, &readfds))
{
/** catch t4 **/
t4=ts();
sprintf(t4_str, "%lld", t4);
/** Receive server message**/
nBytes = recvfrom(clientSocket,cadena_recibida,sizeof(cadena_recibida),0,NULL, NULL);
/** If si a bad data **/
if (nBytes < 0)
{
error( "Error recept data" );
FD_CLR(clientSocket, &readfds);
close(clientSocket);
cont_parametros = 0;
return 1;
}
/** Clean set **/
FD_CLR(clientSocket, &readfds);
int i;
/** trim t2**/
for(i=17;i<33;i++) t2_str_rec[i-17]=cadena_recibida[i];
t2_str_rec[16]= '\0';
/** trim t3**/
for(i=34;i<51;i++) t3_str_rec[i-34]=cadena_recibida[i];
t3_str_rec[16]= '\0';
printf("%s|%s|%s|%s\n",t1_str_, t2_str_rec, t3_str_rec, t4_str);
return 0;
}
}
}
And the function to set the params socket:
void set_param()
{
/** Set client params **/
memset(&local_addr, 0, sizeof(struct sockaddr_in));
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(SRC_PORT);
local_addr.sin_addr.s_addr = inet_addr(SRC_IP);
/** Configure settings in address struct **/
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(DST_PORT);
serverAddr.sin_addr.s_addr = inet_addr(DST_IP);
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
addr_size = sizeof serverAddr;
clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
if ( clientSocket < 0 )
{
error( "Error socket no create" );
exit(1);
}
if (bind(clientSocket, (struct sockaddr *)&local_addr, sizeof(local_addr))< 0)
{
close(clientSocket);
error( "Error bind in socket" );
exit(1);
}
/** Socket create OK**/
cont_parametros = 1;
}
The main part
int main( int argc, char* argv[] )
{
long long int t1;
char t1_str[20];
while(1)
{
t1=ts();
sprintf(t1_str, "%lld", t1);
consultar_servidor(t1_str);
sleep(1);
}
}
The main problem is that you call
close(clientSocket);
for all branches of the code except when you successfully read the data with recvfrom and return with code 0 from consultar_servidor(). As a result, the socket is never closed and there is a socket descriptor leak.
There may be other bugs in the code, make sure to test it under valgrind.
I suggest to restructure the code to avoid duplication and help to catch bugs such as these. For example, one option is to move the cleanup code to a separate function. Another option is to use the goto cleanup pattern, unless you're paranoid about not having goto in your code.
I don't see any actual memory allocations in the posted code, so if there is a direct memory leak, it must be caused by a problem somewhere else in the program.
As #kfx mentioned, another possibility is a socket leak; since each socket comes with buffers that use up a certain amount of RAM, that could show up as increased memory usage as well.
An easy way to test to see if your program is leaking sockets would be to add something like this to your program:
static int socketCount = 0;
int debug_socket(int domain, int type, int protocol)
{
int ret = socket(domain, type, protocol);
if (ret >= 0)
{
++socketCount;
printf("After socket() call succeeded, there are now %i sockets in use by this program\n", socketCount);
}
else perror("socket() failed!");
return ret;
}
int debug_close(int sock)
{
int ret = close(sock);
if (ret == 0)
{
--socketCount;
printf("After close() call succeeded, there now %i sockets in use by this program\n", socketCount);
}
else perror("close() failed!");
return ret;
}
... then temporarily replace all the calls to socket() in your program with debug_socket(), and all the calls to close() in your program with debug_close().
Then run your program, and watch its stdout output. If the numbers printed in the debug output are constantly increasing, your program is leaking sockets and you'll need to figure out why/how and fix it. If not, then you have some other problem elsewhere.
I have already written a code for receiving files from Android to C, but the problem is i am receiving data loss. There is a mismatch of bytes when the received text file is checked with the original text file. How to eradicate this? I have given the code for reference.`
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/ioctl.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<sys/socket.h>
int receive_text(long int new_socket)
{
int buffersize = 0, recv_size = 0, size = 0, read_size, write_size;
char verify = '1';
int errno;
FILE *text;
char *pBuf;
//Find the size of the text
recv(new_socket, (char *)&size, sizeof(int), 0);
//Send our verification signal
//send(new_socket, &verify, sizeof(char), 0);
text = fopen("/home/sosdt009/Desktop/received.txt", "w");
if (text == NULL)
{
puts("Error has occurred. Text file could not be opened \n");
return -1;
}
//Loop while we have not received the entire file yet
while (recv_size < size)
{
ioctl(new_socket, FIONREAD, &buffersize);
//We check to see if there is data to be read from the socket
if (buffersize > 0)
{
pBuf = malloc(buffersize);
if (!pBuf)
{
fprintf(stderr, "Memory Error. Cannot allocate!\n");
exit(-1);
}
//memset(pBuf,0,buffersize);
read_size = recv(new_socket, pBuf, buffersize, 0);
if (read_size < 0)
{
printf("%s", strerror(errno));
}
//Write the currently read data into our text file
write_size = fwrite(pBuf, 1, buffersize, text);
free(pBuf);
printf("%d \n", write_size);
//Increment the total number of bytes read
recv_size += write_size;
printf(" %d \n", recv_size);
}
}
fclose(text);
return 1;
}
int main(int argc , char *argv[]) {
int socket_desc , new_socket, c, read_size, buffer = 0;
struct sockaddr_in server , client;
char *readin;
//Create socket
socket_desc = socket(AF_INET,SOCK_STREAM,0);
if (socket_desc == -1)
{
printf("Could not create socket:");
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 6777 );
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("bind failed");
return 1;
}
puts("Bind completed");
//Listen
listen(socket_desc,3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
if((new_socket = accept(socket_desc,(struct sockaddr *)&client,(socklen_t *)&c)) )
{
puts("Connection accepted");
}
fflush(stdout);
close(socket_desc);
if (new_socket<0)
{
perror("Accept Failed");
return 1;
}
while(1)
{
receive_text(new_socket);
}
close(socket_desc);
return 0;
}
Here
read_size = recv(new_socket, pBuf, buffersize, 0);
recv() tells you how much bytess it received for the current iteration, namly read_size bytes.
And here
write_size = fwrite(pBuf, 1, buffersize, text);
you ignore the number of bytes received, but always write buffersize.
Fix this by writing to the target file the actual received amount of data:
write_size = fwrite(pBuf, 1, read_size, text);
The call to recv() receiving the number of bytes to come fully misses any error checking.
When transfering binary data you also need to make sure not to stumble over
possible different widths of an integer value on sender and receiver
different Endianness on sender and receiver
To take care of the 1st possible issue above use a well defined data type in terms of bit-width. Here int32_t instead of int or probably the unsigned pedant: unint32_t
For the 2nd possible pitfall tranfer data in network byte order. To achieve this do not send the plain int (or uint32_t) but convert it to network byte-order (prior to sending it) via a call to htonl(). On the receiving side then convert it back to host-byte order using ntohl().
The case that the sender closes the socket during transmission is ignored but should be handled by testing the result of recv() against 0, which indicates the closure of the socket by the sender.
Also casting int c to socklen_t on the call to accept() is possibly provoking undefined behaviour.
To fix this instead of
int c;
define
socklen_t c;
Also2 the code close socket_desc twice and does not close new_socket at all.
Also3 doing
ioctl(new_socket, FIONREAD, &buffersize);
to test whether data is available does make sense, as the socket's buffer is filles asynchronously to the program by the kernel, so the value returned by the call to ioctl() might be outdated within a wink.
Just remove this call to ioctl() and define a fixed-size buffer to read into. recv() will block until data is available.
I have a tcp echo server that creates a pthread for each client that connects to it. For each connection, I have a variable nbOfClients that increments.
When a client closes its connection, I detect it and decrease the number of clients. However the server keeps thinking that the client it alive and keeps on trying to read/write from the socket. I guessed that it was because of the thread that created the client and I tries to kill the thread with pthread_cancel all to non avail.
I want to kill the pthread associated to a certain client that closes its connection.
How can I go about it?
Here's my code :
static int nbOfClients = 0;
static pthread_t tid;
int main (int argc, char *argv[]) {
int bytes_to_read, arg, listen_sd, new_conn, sockfd, client_len, port;
struct sockaddr_in server, client_addr;
char *bp, buf[BUFLEN];
ssize_t n;
sockfd = 0;
switch(argc) {
case 1:
port = SERVER_TCP_PORT; // Use the default port
break;
case 2:
port = atoi(argv[1]); // Get user specified port
break;
default:
fprintf(stderr, "Usage: %s [port]\n", argv[0]);
exit(1);
}
// Create a stream socket
if ((listen_sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
error("Cannot Create Socket!");
// set SO_REUSEADDR so port can be resused imemediately after exit, i.e., after CTRL-c
arg = 1;
if (setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) == -1)
error("setsockopt");
// Bind an address to the socket
bzero((char *)&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = htonl(INADDR_ANY); // Accept connections from any client
if (bind(listen_sd, (struct sockaddr *)&server, sizeof(server)) == -1)
error("bind error");
listen(listen_sd, MAX_CONNECTIONS); ///put a define constant indicating the maximum number of clients #define NB_CLIENTS 3
while (TRUE) {
client_len = sizeof(client_addr);
if ((new_conn = accept(listen_sd, (struct sockaddr *) &client_addr, (socklen_t *)&client_len)) == -1)
error("accept error");
if(new_conn > 0) {
if(nbOfClients < MAX_CONNECTIONS) {
printf("just here\n");
printf(">> Initializing remote address: %s\n", inet_ntoa(client_addr.sin_addr));
nbOfClients++;
fclose(fp);
printf("Connections to date: %u \n",nbOfClients);
printf("make thread\n");
pthread_create(&tid,NULL,&echo, (void *)new_conn);
printf("had thread\n");
}
else {
printf("connection limit reached\n");
if(send(new_conn, "Server full!\n", 13, 0) == -1)
perror("send");
close(new_conn);
}
}
}
return(0);
}
void * echo(void *arg) {
char buf[BUFSIZE]; /* message buffer */
int n, i = 0;
bzero(buf, BUFSIZE);
if(send((int)arg, "Welcome!!\n", 20, 0) == -1)
perror("send");
detect_closed_connection(arg);
while(TRUE) {
n = read((int)arg, buf, BUFSIZE);
/**read: read input string from the client*/
if(n < 0) {
perror("error reading from socket");
}
printf("Server received from client, %d bytes: %s\n", n, buf);
/**write: echo the input string in UPPERCASE back to the client*/
int len = strlen(buf);
for(i = 0; buf[i]; i++)
buf[i] = toupper(buf[i]);
n = write((int)arg, buf, len);
if(n < 0) {
error("ERROR writing to socket");
}
}
}
void detect_closed_connection(void * listenSocket) {
struct pollfd pfd;
pfd.fd = (int)listenSocket;
pfd.events = POLLIN | POLLHUP | POLLRDNORM;
pfd.revents = 0;
while(pfd.revents == 0) {
if(poll(&pfd, 1, 100) > 0) {
// if result > 0, this means that there is either data available on the
// socket, or the socket has been closed
char buffer[32];
if (recv((int)listenSocket, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
// if recv returns zero, that means the connection has been closed:
nbOfClients--;
pthread_cancel(tid);
}
}
}
}
Thanks.
You should check read() for returning 0 in the thread servering the client, as read() returns 0 in case the peer (client here) closed the connection.
After this line
n = read((int)arg, buf, BUFSIZE);
add
if (0 == n)
{
fprintf(stderr, "The client closed the connection.\n");
break;
}
Just before the thread function leave you could add the statement to decrement the number of running threads.
Also be aware that nbOfClients is accessed concurently by all the "client"-threads as well as by the main thread, so accessing it shall be protected, for example by using a mutex.
There is another issues, as the call to strlen() on the buffer read expects the buffer to be 0-terminate, which does not necessarily needs ot be the case, even if you sent 0-terminated "strings". read() might very well return the "string" the client sent in more then one part. So loop around read() until the 0-terminator had been received.
Do not make the thread end itself by calling pthread_cancel(), use pthread_exit() instead.
/* SEND FUNC. */
int mysend(unsigned char *buffer, int len) {
int sock,ret;
int status,flags;
struct sockaddr_in6 servaddr;
int opt = 1;
char *addr = "1101::1";
sock = socket(AF_INET6,SOCK_DGRAM,0);
if (sock < 0)
return -1;
if( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 )
return -1;
flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags|O_NONBLOCK);
servaddr.sin6_family = AF_INET6;
servaddr.sin6_port = htons(61616);
status = inet_pton(AF_INET6, addr, &servaddr.sin6_addr);
if (status <= 0) {
perror("inet_pton");
return -1;
}
/* send message to server */
status = sendto(sock, buffer, len, 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
if (status < 0) {
perror("sendto");
return -1;
}
close(sock);
printf("MESSAGE SENT SUCCESSFULLY\n");
return 0;
}
/* RECEIVE FUNC. */
int myrcv() {
int sock,ret;
int status,len,rx_bytes;
int timeout,nfds =1;
struct sockaddr_in6 servaddr;
struct timeval wait;
unsigned char rxbuff[1024];
char *rcv;
char *addr = "1101::1";
fd_set rd;
struct pollfd *fds;
sock = socket(AF_INET6,SOCK_DGRAM,0);
if (sock < 0)
return -1;
servaddr.sin6_family = AF_INET6;
servaddr.sin6_port = htons(61616);
status = inet_pton(AF_INET6, addr, &servaddr.sin6_addr);
if (status <= 0)
return -1;
bind(sock,(struct sockaddr *)&servaddr,sizeof(servaddr));
timeout = (1* 1000);
wait.tv_sec = 10;
wait.tv_usec = 0;
len = sizeof(servaddr);
fds->fd = sock;
fds->events = POLLIN;
for(;;) {
//FD_ZERO(&rd);
//FD_SET(sock,&rd);
printf("Waiting for data....\n");
ret = poll(fds,nfds,timeout);
//ret = select(1,&rd,NULL,NULL,&wait);
if(ret < 0)
break;
if(fds->revents == 0)
printf("revents 0 %d\n",ret);
if(ret == 0)
continue;
memset(rxbuff,0,1024);
//if(FD_ISSET(sock,&rd)) {
printf("receiving message\n");
rx_bytes = recvfrom(sock,rxbuff,1024,0,(struct sockaddr *)&servaddr,&len);
memcpy(rcv,rxbuff,rx_bytes);
//}
}
close(sock);
return 0;
}
int main()
{
/* call mysend() periodically using sigaction() */
/* create a thread that continuously monitors(calls myrcv()) for incoming data */
return 0;
}
I'm unable to receive the packets from the server, but I could see the packets in the tcpdump output. Above are the sample client code snippets, which tries to receive and send the data from/to the server. The scenario is: the client needs to send data periodically to server and should also be able to receive any data from the server.
I have tried using both poll and select methods but failed to receive. Please let me know if I'm missing anything. Thanks for your support.
The problem you have with receiving is that you need to bind the receiving socket to the local port.
You also have other things that can be improved, like creating a single socket for both sending and receiving and using SO_REUSEADDR on the sending socket (not needed on a write-only socket).
What you should do is:
Create socket
Set socket options
Bind to local address (Use IN6ADDR_ANY_INIT to bind to all interfaces)
Write to server
Poll for reply
Several things:
Your receive function (myrcv) isn't specifying a listen port via the bind() call. That's the most likely problem. Ditto for your send function, although a port is chosen randomly for you.
In you myrcv() function, I don't see where you have actually initialized fds or nfsd prior to calling poll().
Re-opening and closing the socket on each call to mysend() looks problematic. If you are expecting the server to send back to the same client on the same port it received the message on, chances are high you have already closed the socket. You should just open one socket for both sending and receiving. You can share the same socket between your send thread and your receive thread.