Forwarding data as TCP Client - c

I have a client requesting data (DA) from server A, and then I need to send DA to a second server B. I got it while the data is not larger than the buffer. However the following is not working for passing all data from A to B. I notice that when I create the socket_fwd and connect after closing the first sockfd, it works. But since I need to forward all data, I need to process all incomming as soon as it arrives
int sockfd, sockfd_fwd, n, n_fwd;
gint BUFFER=900;
char buf[BUFFER];
char* addr = "11.0.0.20"; //Server A listening on port 80
struct sockaddr_in server_addr = {0};
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(80);
char chunk[BUFFER];
gint nfw;
gint total_recv = 0;
gint total_fwd = 0;
struct sockaddr_in server_addr2 = {0};
server_addr2.sin_port = htons(5555);
server_addr2.sin_family = AF_INET;
char *addr2 = "127.0.0.1"; //Server B listening on port 555
//#################Request data from A:80 ###########################
if(inet_pton(AF_INET, addr, &server_addr.sin_addr) != 1){
perror("inet_pton");
return -1;
}
sockfd = socket(AF_INET, (SOCK_STREAM), 0); //socket with server A
if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
mylog(G_LOG_LEVEL_MESSAGE, __FUNCTION__,"Error on connect");
send(sockfd, buffer, strlen(buffer), 0); //Buffer contains something like get xx Kib to the server
bzero(buffer, BUFFER);
if(inet_pton(AF_INET, addr2, &server_addr2.sin_addr) != 1){
mylog(G_LOG_LEVEL_MESSAGE, __FUNCTION__,"Error inet pton");
return -1;
}
if(inet_pton(AF_INET, addr2, &server_addr2.sin_addr) != 1){
perror("inet_pton");
return -1;
}
sockfd_fwd = socket(AF_INET, (SOCK_STREAM), 0); //socket with server B
if (connect(sockfd_fwd, (struct sockaddr*)&server_addr2, sizeof(server_addr2)) < 0)
mylog(G_LOG_LEVEL_MESSAGE, __FUNCTION__,"Error on connect");
while ((n = recv(sockfd, chunk, BUFFER, 0)) > 0) {
total_recv += n;
mylog(G_LOG_LEVEL_MESSAGE, __FUNCTION__,"Recv chunk %s num-bytes:%i",chunk,total_recv);
nfw = send(sockfd_fwd, chunk ,n, 0);
memset(chunk,0,BUFFER);
}
close(sockfd);
close(sockfd_fwd);

Related

my recv breaks my send which is just before

I'm trying to make a program that uses sockets between a client and a server. In my code below if I comment on the loop while my server receives my message but if I do not comment my client seems not to send my message (finally my server never receives my message). Why ?
Server
int main()
{
message = malloc(sizeof(char));
printf("Waiting for incoming connections ...\n");
sem_init(&lock, 0, 1);
// socket creation
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
// dserver address9002
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);
server_address.sin_addr.s_addr = INADDR_ANY;
// bind the socket to IP and port
bind(server_socket, (struct sockaddr*) &server_address, sizeof(server_address));
listen(server_socket, MAX_CONNECTIONS);
int client_socket;
int i = 0;
while(client_counter < 2 && (client_socket = accept(server_socket, NULL,NULL)))
{
client_counter++;
client_sockets[i] = client_socket;
i++;
printf("new client ! \n");
}
//here i create a thread for each client and in this thread there is a while loop with a recv function
}
Client
int socket_connection(char* ip, int port)
{
int network_socket = 0;
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(port);
server_address.sin_addr.s_addr = inet_addr(ip);
if ((network_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
int connection_status = connect(network_socket, (struct sockaddr*) &server_address, sizeof(server_address));
if (connection_status < 0)
{
printf("Error while creating / connecting the socket");
return -1;
}
return network_socket;
}
void connect_to_server()
{
char ip[256];
int port;
strcpy(ip, "127.0.0.1");
port = 9002;
// try to connect to the server with the IP and port
int network_socket = socket_connection(ip, port);
char server_reponse[256];
char message[256];
// clean string
memset(server_reponse, 0, sizeof(server_reponse));
recv(network_socket, &server_reponse, sizeof(server_reponse), 0);
if (strcmp(server_reponse, "instruction: make board") == 0)
{
construct_game_board();
show_game_board();
memset(message, 0, sizeof(message));
put_ship(message);
printf("Finish to make board\n");
}
printf("Reponse send to socket %d: %zu\n",network_socket, send(network_socket, message, strlen(message), 0));
while (1) {
printf("Before recv\n");
printf("Reponse recv : %zu\n", recv(network_socket, server_reponse, sizeof(server_reponse), 0));
printf("After recv\n");
}
In my console when i launch i have : Reponse send to socket 3: 0 and Before recv

What is the reason I am getting: Socket operation on non-socket

I am writing c sockets the send a file from client to server. client() is called in main client program while the server() is called in the server program. send_file() is a helper function for client(). I want the server to wait for another client connection after it finishes getting data from the current client.
The first iteration is fine but I am getting error from accept in the SECOND iteration in the server: server: accept: Socket operation on non-socket
What causes the problem?
int send_file(int socket, char *path) {
int len;
char buf[BUF_SIZE];
char size[BUF_SIZE];
struct stat stbuf;
int fd = open(path, O_RDONLY);
fstat(fd, &stbuf);
sprintf(size, "%d", (int)stbuf.st_size);
write(socket, size, BUF_SIZE);
while((len = read(fd, buf, BUF_SIZE)) > 0) {
write(socket, buf, len);
}
close(fd);
return 1;
}
int client(char *src_path, char *dest_path, char *host_ip, int port) {
int sock_fd;
// Create the sock fd
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0) {
perror("client: socket");
exit(1);
}
// Set the IP and port of the server to connect to.
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
if (inet_pton(AF_INET, host_ip, &server.sin_addr) < 1) {
perror("client: inet_pton");
close(sock_fd);
exit(1);
}
// Connect to the server
if (connect(sock_fd, (struct sockaddr *)&server, sizeof(server)) == -1) {
perror("client: connect");
close(sock_fd);
exit(1);
}
send_file(sock_fd, src_path);
return 0;
}
int server(int port) {
printf("PORT: %d\n", port);
char buf[BUF_SIZE];
int sock_fd, client_fd;
int len;
// Create the socket FD.
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0) {
perror("server: socket");
exit(1);
}
// Set information about the port (and IP) we want to be connected to.
struct sockaddr_in server, client;
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = INADDR_ANY;
memset(&server.sin_zero, 0, 8);
// Bind the selected port to the socket
if (bind(sock_fd, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("server: bind");
close(sock_fd);
exit(1);
}
// Announce willingness to accept connections on this socket
if (listen(sock_fd, MAX_BACKLOG) < 0) {
perror("server: listen");
close(sock_fd);
exit(1);
}
while(1) {
socklen_t client_size = sizeof(client);
if ((client_fd = accept(sock_fd, (struct sockaddr *)&client, &client_size)) < 0) {
perror("server: accept");
close(sock_fd);
exit(1);
}
read(client_fd, buf, BUF_SIZE);
int size = atoi(buf);
printf("Size: %d\n", size);
while ((size > 0) && ((len = read(client_fd, buf, BUF_SIZE)) > 0)) {
size -= len;
buf[len] = '\0';
printf("%s", buf);
}
close(client_fd);
}
close(sock_fd);
exit(1);
}
You have a buffer overflow in your read code on the server.
while ((size > 0) && ((len = read(client_fd, buf, BUF_SIZE)) > 0)) {
size -= len;
buf[len] = '\0';
// ^^^ Boom!!!
printf("%s", buf);
}
If you read BUF_SIZE bytes from the socket, len is BUF_SIZE and then you set the byte at buf[BUF_SIZE] to \0. This must be clobbering the socket file descriptor which is declared straight after the buffer.
I should add, the best way to fix it is probably to declare the buffer with size BUF_SIZE + 1 rather than read BUF_SIZE - 1 bytes because the IO will be a bit more efficient (you are writing in BUF_SIZE chunks).

C Sockets - send() sends, recv() not receiving

So I'm doing some client server stuff here, and I want my server to listen for clients, and when a client connects to the server, the client sends a string.
The connection establishes, the clients sends it's string, but, at server side, recv() returns -1.
/* Server */
int main() {
int fd, conn_fd;
struct sockaddr_in ad;
int bytes;
char recv_buffer[256];
fd = socket(AF_INET, SOCK_STREAM, 0);
ad.sin_family = AF_INET;
ad.sin_port = htons(3335);
ad.sin_addr.s_addr = htonl(INADDR_ANY);
bind(fd, (struct sockaddr*)&ad, sizeof(ad));
listen(fd, 5);
conn_fd = accept(fd, (struct sockaddr*)0, 0);
bytes = recv(fd, recv_buffer, sizeof(recv_buffer), 0);
printf("%d\n", bytes);
return 0;
}
The clients simply connects to the server:
/* Client */
int main() {
int fd, n;
unsigned int s;
struct sockaddr_in addr;
fd = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = htons(3335);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
char buff[256] = "time";
printf("Connecting to server....\n");
if(connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
printf("connect() error.\n");
exit(1);
}
s = send(fd, buff, sizeof(buff), 0);
return 0;
}
Thanks!
I found out what the problem was. In my server code, I was using the wrong socket descriptor for recv(): instead of fd, I should have used conn_fd.

C TCP Socket recv return -1 on Server-Server communication

I am building a client-server socket simulation to emulate DHCP. I have a client that receives input from the user, then sends a request via UDP to Server1. If Server1 does not hold the requested information, it contacts Server2 via TCP. If Server2 does not hold the information, it contacts Server3. Server3 then sends information to Server2 then Server1 then on to the Client
My code works for Client --> Server1 --> Server2 --> Server1 --> Client, but it fails when I try to add Server3.
Server3 successfully receives the connection and data from Server2, and the send is successful I believe. However, the recv on server 2 returns -1.
Here is my Server3 send code:
while ((rqst = accept(svc,(struct sockaddr *) &client_addr, &alen)) < 0) {
/* we may break out of accept if the system call */
/* was interrupted. In this case, loop back and */
/* try again */
}
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
recvlen = recv(rqst, buf, BUFSIZE - 1, 0);
if (send(rqst, "Hello Server2!\0", BUFSIZE, 0) < 0) { /* Not real message, but this works */
perror("sendto");
}
My Server2 recv code is here
int port = SERVICE_PORT3; /* default: whatever is in port.h */
char *host = "localhost"; /* default: this host */
if (!conn_and_send(host, port, buf, fd3)) { /* connect fd3 is global int */
exit(1); /* something went wrong */
}
else {
char serv3_buf[BUFSIZE];
int serv3_recvlen = recv(fd3, serv3_buf, BUFSIZE - 1, 0);
printf("The recv length from serv3 is: %d\n", serv3_recvlen); /* prints -1*/
}
This is my conn_and_send function
int conn_and_send(char *host, int port, char* request, int fd_sock)
{
struct hostent *hp; /* host information */
unsigned int alen; /* address length when we get the port number */
struct sockaddr_in myaddr; /* our address */
struct sockaddr_in servaddr; /* server address */
printf("conn(host=\"%s\", port=\"%d\")\n", host, port);
if ((fd_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("cannot create socket");
return 0;
}
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(0);
if (bind(fd_sock, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
perror("bind failed");
return 0;
}
alen = sizeof(myaddr);
if (getsockname(fd_sock, (struct sockaddr *)&myaddr, &alen) < 0) {
perror("getsockname failed");
return 0;
}
printf("local port number = %d\n", ntohs(myaddr.sin_port));
memset((char*)&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port);
hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "could not obtain address of %s\n", host);
return 0;
}
memcpy((void *)&servaddr.sin_addr, hp->h_addr_list[0], hp->h_length);
if (connect(fd_sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("connect failed");
return 0;
}
printf("Getting ready to send: %s\n", request);
if (send(fd_sock, request, strlen(request), 0) < 0) {
perror("sendto");
exit(1);
}
return 1;
}
Sorry to post so much code. I tried to include only relevant snippets.
What am I doing wrong, and if you can see no problems besides my poor C coding, why does C hate me?! :P

How to reduce message dropping in UDP socket communication, using only single port?

I have writter code snippet for UDP Client and server. I am using same port for sending and receiving. My problem is that there are many messages drops at client side, so can someone help me to optimize my code, here is my code for UDP client:
#define SERVERIP "192.168.170.155"
#define SERVERPORT 5000
#define DEVICE_SEND_PORT 5000
#define DEVICE_RECEIVE_PORT 5000
#define BUFFERSIZE 2048
/**For socket file descriptor identification*/
#define S1READY 0x01
int m_SendSocketId;
int m_ReceiveSocketId;
int msgcount;
int socketbuffsize = 1*1024*1024;
/**
* FUNCTION NAME : waitToRead
* Implementation of select and non-blocking socket mechanism
* #param socket Socket that needs to be in select and non blocking mode
* #return Returnd the file descriptors which, returned by select function
*/
int waitToRead(int socket)
{
fd_set fds;
struct timeval timeout;
int rc; // number of file descriptor returned
int result; // result
int fd; // file descriptor
fd=fcntl(socket,F_GETFL,0);
fcntl(socket,F_SETFL,fd | O_NONBLOCK);
// Set time limit.
timeout.tv_sec = 1;
timeout.tv_usec = 0;
// Create a descriptor containing our sockets.
FD_ZERO(&fds);
FD_SET(socket, &fds);
rc = select(sizeof(fds)*8, &fds, NULL, NULL, &timeout);
if (rc==-1)
{
printf("[%s:%d#%s] Select Failed\n",__FILE__, __LINE__,__func__);
return -1;
}
result = 0;
if (rc > 0)
{
if (FD_ISSET(socket, &fds))
result |= S1READY;
}
return result;
}
/**
* FUNCTION NAME : receiveMessage
* This function opens particular port that is defined in the
* Configuration file, and listens on that port.
* #return if there'll be any issue in listening, then it will return
* false otherwise it will return true.
*/
bool receiveMessage()
{
struct sockaddr_in serverAddr; //Information about the Device UDP Server
struct sockaddr_in client_addr; // Information about Qgate Server
char buffer[BUFFERSIZE]; // Buffer to store incoming message
int addr_len; // to store client address length
int serverlen; // to store server address length
int sockResult; // to store result given by waitToRead
int optval = 1;
int receivedByte = 0;
//Open a datagram Socket
if((m_ReceiveSocketId = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
printf("[%s:%d#%s] UDP Client - socket() error\n",__FILE__, __LINE__,__func__);
return false;
}
//Configure Server Address.
//set family and port
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(DEVICE_RECEIVE_PORT);
setsockopt(m_ReceiveSocketId, SOL_SOCKET,SO_REUSEADDR, &optval, sizeof(optval));
/*if (setsockopt(m_ReceiveSocketId, SOL_SOCKET, SO_RCVBUF, &socketbuffsize, sizeof(socketbuffsize)) == -1)
{
printf("Recieve Socket memory Allocation fail\n");
}*/
if((serverAddr.sin_addr.s_addr = INADDR_ANY) == (unsigned long)INADDR_NONE)
{
printf("[%s:%d#%s] Host Not found(%d)\n",__FILE__, __LINE__,__func__,h_errno);
close(m_ReceiveSocketId); // close the socket
return false;
}
if (bind(m_ReceiveSocketId, (struct sockaddr *) &serverAddr,sizeof(struct sockaddr_in)) < 0 )
{
printf("[%s:%d#%s] UDP Client- Socket Bind error=%s\n",__FILE__, __LINE__,__func__,strerror(errno));
close(m_ReceiveSocketId); // close the socket
return false;
}
serverlen = (int )sizeof(serverAddr);
addr_len = sizeof(struct sockaddr);
// Loop and listen for incoming message
while(1)
{
//wait at select to, read
sockResult = waitToRead(m_ReceiveSocketId);
if(sockResult == S1READY)
{
receivedByte = read(m_ReceiveSocketId,buffer,BUFFERSIZE);
buffer[receivedByte] = '\0';
if(receivedByte == -1)
{
printf("[%s:%d#%s] UDP Client - receive error", __FILE__,__LINE__,__func__);
close(m_ReceiveSocketId);
return false;
}
else if(receivedByte > 0)
{
//printf("[%s:%d#%s] received message = %d bytes\n",__FILE__,__LINE__,__func__,(int)strlen(buffer));
printf("count: %d, buffer %s \n", msgcount++, buffer);
}
}
memset(buffer, 0, BUFFERSIZE);
fflush(stdout);
}
close(m_ReceiveSocketId); // close the socket
printf("[%s:%d#%s] Recieve socket closed:%s\n",
__FILE__, __LINE__,__func__, strerror(errno));
return true;
}
bool sendMessage(char *message)
{
struct sockaddr_in serverAddr; //Information about the server
struct sockaddr_in deviceAddr; //Device UDP Client Address for sending message
int optval = 1;
//Open a datagram Socket
if((m_SendSocketId = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
printf("[%s:%d#%s] UDP Client - socket() error\n",__FILE__, __LINE__,__func__);
return false;
}
// Clear out the device struct
memset(&deviceAddr, 0x00, sizeof(struct sockaddr_in));
deviceAddr.sin_family = AF_INET;
deviceAddr.sin_port = htons(DEVICE_SEND_PORT);
setsockopt(m_SendSocketId, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
/*if (setsockopt(m_SendSocketId, SOL_SOCKET, SO_SNDBUF, &socketbuffsize, sizeof(socketbuffsize)) == -1)
{
printf("send Socket memory Allocation fail\n");
}*/
if((deviceAddr.sin_addr.s_addr = INADDR_ANY) == (unsigned long)INADDR_NONE)
{
// in netdb.h
printf("[%s:%d#%s] Host Not found(%d)\n",__FILE__, __LINE__,__func__, h_errno);
close(m_SendSocketId); // close the socket
return false;
}
if (bind(m_SendSocketId, (struct sockaddr *) &deviceAddr,sizeof(struct sockaddr_in)) < 0 )
{
printf("[%s:%d#%s] UDP Client- Socket Bind error=%s\n",__FILE__, __LINE__,__func__,strerror(errno));
close(m_SendSocketId); // close the socket
return false;
}
// Clear out the server struct
memset(&serverAddr, 0x00, sizeof(struct sockaddr_in));
//Configure Server Address.
//set family and port
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(SERVERPORT);
//serverAddr.sin_addr.s_addr = htonl(39898);
if((serverAddr.sin_addr.s_addr = inet_addr(SERVERIP)) == (unsigned long)INADDR_NONE)
{
printf("[%s:%d#%s] Host Not found %d\n",__FILE__, __LINE__,__func__,h_errno);
close(m_SendSocketId);
return false;
}
// Send data to the server.
if( sendto(m_SendSocketId, message,strlen(message) ,0, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0 )
{
printf("[%s:%d#%s] UDP Client - sendto() error=%s \n",__FILE__, __LINE__,__func__,strerror(errno));
close(m_SendSocketId);
return false;
}
close(m_SendSocketId);
return true;
}
int main ()
{
int loop;
char str[10];
msgcount = 1;
pthread_t receiveThread;
if(pthread_create(&receiveThread, NULL,(void *)&receiveMessage, NULL) != 0)
{
printf("[%s:%d#%s] thread create Failed(%s)\n",
__FILE__, __LINE__,__func__, strerror(errno));
return false;
}
for(loop =0; loop < 1000; loop++)
{
sprintf(str,"%4d",loop);
sendMessage(str);
}
pthread_join(receiveThread, NULL);
return 0;
}
Here is the temporary UDP server code, it receives almost above 90% messages and also sends the same, but udpclient is not able to receive the messages.
int main()
{
int sock;
int addr_len, bytes_read, bytes_send;
char recv_data[1024];
int i;
int count=0;
struct sockaddr_in server_addr , client_addr;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5000);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero),8);
//client_addr.sin_family = AF_INET;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
if (bind(sock,(struct sockaddr *)&server_addr,sizeof(struct sockaddr)) == -1)
{
perror("Bind");
exit(1);
}
addr_len = sizeof(struct sockaddr);
printf("\nUDPServer Waiting for client on port 5000");
fflush(stdout);
while (1)
{
bytes_read = recvfrom(sock,recv_data,1024,0,(struct sockaddr *)&client_addr, (socklen_t *)&addr_len);
recv_data[bytes_read] = '\0';
if(recv_data[0]!=0x07)
{
recv_data[0] = 0x09;
//client_addr.sin_port = htons(51254);
bytes_send = sendto(sock, recv_data, bytes_read, 0, (struct sockaddr *)&client_addr, (socklen_t)sizeof(client_addr));
if(bytes_send < 0 )
{
perror("send to ");
}
printf("\nNumber %d", ++count);
memset(&recv_data, 0x00, 1024);
}
else
{
printf("Received Keep ALive\n");
}
memset(&client_addr, 0x00, sizeof(struct sockaddr_in));
fflush(stdout);
}
return 0;
}
Any help would be highly appreciated.
Thanks Yuvi
Your code has nothing to do with UDP dropping packets, except possibly that you are sending packets too fast for the network or the receiver. UDP isn't reliable. It drops packets. If your application protocol requires no dropped packets, you have to build in reliability at that level, via an ACK-based or NACK-based protocol with retries.
Or use TCP like everybody else does in this situation.
The problem was in sendMessage Function, here I was recreating socket every time when I need to send message, and I think that takes time. I don't know yet which is calls are blocking but making sending socket resolves my problem. Now the dropping of message is upto 20 to 30 % only.

Resources