Eddie  Lin Eddie Lin - 1 month ago 10
C Question

when client write the message to the server, but server cannot read the message from the client in sokcet in c/c++ on linux

My OS is linux. I program socket in C. I tested the client and the server at the same time. Both of them are on my localhost. However, when the client write the message to the server, but the server cannot read the message from the client. I have no idea that what wrong it is. I'm sure that the client and the server connect to each other. My main purpose is that the client write the message, whose content is the sequence number, to the server, and then the server can reply the message to the client back.

I use pthread to make the client can connect to the multiple servers.
the part function code from the client.c:

#include<stdio.h>
#include<string.h> //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<netdb.h> //hostent
#include <pthread.h>
#include <ctype.h>
#include <stdint.h>
#include <limits.h>
#include <assert.h>
#include <sys/time.h>
#include <pthread.h>
#include <sys/select.h>
#include <unistd.h>
#include <fcntl.h>
#define NAMEMAX 4096
int socket_desc;
int packet_num;
struct timeval timeout;
typedef struct server_object{
char server_ip[100];
uint16_t server_port;
struct sockaddr_in server_about;
}server_object;

void* request(void* server_func){
server_object* server_pointer = (server_object*) server_func;
struct timeval start;
struct timeval end;
struct timeval thistimeout;
int num = 0;
//Connect to remote server
int test_con = connect(socket_desc , (struct sockaddr *)&(server_pointer->server_about) , sizeof(server_pointer->server_about));
printf("test_con = %d\n", test_con);
fd_set read_fd2;
FD_ZERO(&read_fd2);
FD_SET(socket_desc, &read_fd2);
int fdmax2;
fdmax2 = socket_desc;
/*int ret2 = select(fdmax2+1, &read_fd2, NULL, NULL, &thistimeout);
if(ret2 == 0){
printf("00\n");
printf("timeout when connect to %s:%u, seq = %d\n", server_pointer->server_ip, server_pointer->server_port, num);
fflush(stdout);
return 0;
}*/
//puts("Connected\n");
//Send some data
//while-loop begin
int overtime = 0;
while((num < packet_num && packet_num != 0) || (packet_num == 0)){
char msg[200];
memset(msg, 0, sizeof(msg));
//strcpy(msg, "GET / HTTP/1.1\r\n\r\n");
sprintf(msg, "%d", num);
unsigned long diff;
gettimeofday(&start,NULL);
printf("msg = %s\n", msg);
ssize_t write_s;
write_s = write(socket_desc, msg, sizeof(msg));
printf("write_s = %ld\n", write_s);
printf("msg = %s\n", msg);
//puts("write failed");
assert(num <= INT_MAX);
//puts("Data Send\n");
fd_set read_fd;
FD_ZERO(&read_fd);
FD_SET(socket_desc, &read_fd);
int fdmax;
fdmax = socket_desc;
//int ret = select(fdmax+1, &read_fd, NULL, NULL, &thistimeout);
//if(ret == 0){
// overtime = 1;
// break;
//}
//Receive a reply from the server
char buf[2000];
printf("readbef\n");
read(socket_desc, buf, sizeof(buf));
printf("readafter\n");
printf("buf = %s\n", buf);
gettimeofday(&end,NULL);
diff = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec;
thistimeout.tv_usec -= diff;
//printf("thedifference is %ldmsec\n",diff);
//printf("buf = %s\n", buf);
//puts("Reply received\n");
printf("recv from %s:%u, seq = %d, RTT = %lu msec\n", server_pointer->server_ip, server_pointer->server_port, num, diff);
fflush(stdout);
num++;
}
if(overtime == 1){
printf("timeout when connect to %s:%u, seq = %d\n", server_pointer->server_ip, server_pointer->server_port, num);
fflush(stdout);
}
return 0;
}

int main(int argc , char *argv[]){
sscanf(argv[1], "%d", &packet_num);
//printf("packet_num = %d\n", packet_num);
timeout.tv_sec = 0;
sscanf(argv[2], "%lu", &timeout.tv_usec);
//printf("timeout.tv_sec = %lu, timeout.tv_usec = %lu\n", timeout.tv_sec, timeout.tv_usec);
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
printf("socket_desc = %d\n", socket_desc);
int j = 3;
int t;
int isip = 1;
while(j < argc){
//int new_socket
//struct sockaddr_in server;
server_object server;
char hostname[NAMEMAX] = {0};
uint16_t portnum = 0;
int meet = 0;
int k;
for(k = 0; k < strlen(argv[j]); k++){
if(argv[j][k] == ':'){
//portnum = argv[j]+(k+1);
meet = 1;
t = (k+1);
continue;
}
if(meet == 0){
hostname[k] = argv[j][k];
if(isdigit(argv[j][k]) || argv[j][k] == '.'){
isip = 1;
}
else{
isip = 0;
}
}
if(meet == 1){
portnum = portnum*10 + (argv[j][k] - '0');
}
}
char ip[100];
memset(ip, 0, sizeof(ip));
struct hostent *he;
struct in_addr **addr_list;
int i;
struct in_addr hipaddr;
if(isip){
inet_aton(hostname, &hipaddr);
he = gethostbyaddr(&hipaddr, 4, AF_INET);
}
else{
he = gethostbyname( hostname );
}
//Cast the h_addr_list to in_addr , since h_addr_list also has the ip address in long format only
addr_list = (struct in_addr **) he->h_addr_list;
for(i = 0; addr_list[i] != NULL; i++){
//Return the first one;
strcpy(ip , inet_ntoa(*addr_list[i]) );
}

//printf("%s resolved to : %s\n" , hostname , ip);
strcpy(server.server_ip, ip);
//printf("port = %u\n", portnum);
server.server_port = portnum;
server.server_about.sin_addr.s_addr = inet_addr(ip);
server.server_about.sin_family = AF_INET;
server.server_about.sin_port = htons(portnum);
//thread start
pthread_t ntid;
pthread_create(&ntid, NULL, request, &server);
sleep(10);
j++;
}
return 0;
}


I use pthread to make the server can accept the multiple clients.
the part function code from the server.c:

#include <stdio.h>
#include <string.h> //strlen
#include <stdlib.h> //strlen
#include <sys/socket.h>
#include <arpa/inet.h> //inet_addr
#include <unistd.h> //write
#include <pthread.h> //for threading , link with lpthread
#include <netinet/in.h>
#include <sys/time.h>
int sv_socket_desc;
typedef struct client_object{
struct sockaddr_in client_about;
int client_fsd;
}client_object;

void *connection_handler(void *);

int main(int argc , char *argv[]){
int new_socket , c;
struct sockaddr_in server , client;
//Create socket
sv_socket_desc = socket(AF_INET , SOCK_STREAM , 0);
printf("sv_socket_desc = %d\n", sv_socket_desc);
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
//uint16_t portnum;
//sscanf(argv[1], "%hu", &portnum);
//server.sin_port = htons(portnum);
server.sin_port = htons( 8888 );
//Bind
bind(sv_socket_desc,(struct sockaddr *)&server , sizeof(server));
//Listen
listen(sv_socket_desc , 3);
//Accept and incoming connection
c = sizeof(struct sockaddr_in);
while( (new_socket = accept(sv_socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) ){
//puts("Connection accepted");
//Reply to the client
client_object* new_sock;
client_object newclient;
newclient.client_about = client;
newclient.client_fsd = new_socket;
//start thread
fflush(stdout);
pthread_t sniffer_thread;
new_sock = (client_object*)malloc(sizeof(client_object));
*new_sock = newclient;
fflush(stdout);
pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock);
sleep(10);
//thread over
//Now join the thread , so that we dont terminate before the thread
pthread_join( sniffer_thread , NULL);
//puts("Handler assigned");
}
return 0;
}

/*
* This will handle connection for each client
* */
void *connection_handler(void *socket_desc){
//Get the socket descriptor
client_object newclient = *(client_object*) socket_desc;
ssize_t read_size;
char client_message[200];
memset(client_message, 0, sizeof(client_message));
unsigned short int client_port_num = ntohs(newclient.client_about.sin_port);
char client_addr[2000];
inet_ntop(AF_INET6, &(newclient.client_about.sin_addr.s_addr), client_addr, INET6_ADDRSTRLEN);
/*fflush(stdout);
read_size = read(sv_socket_desc, client_message, sizeof(client_message));
printf("client_msg = %s\n", client_message);
printf("read_size = %ld\n", read_size);
fflush(stdout);*/
while(1){
//(read_size = read(sv_socket_desc, client_message, sizeof(client_message))) >= 0
//printf("readbef\n");
read_size = read(sv_socket_desc, client_message, sizeof(client_message));
printf("read_size = %ld\n", read_size);
printf("client_message = %s\n", client_message);
fflush(stdout);
read_size = write(sv_socket_desc, client_message, sizeof(client_message));
int n;
sscanf(client_message, "%d", &n);
printf("recv from %s:%hu, seq = %d\n", client_addr, client_port_num, n);
fflush(stdout);
}
fflush(stdout);
//Free the socket pointer
free(socket_desc);
return 0;
}

Answer

@Eddie Lin, you passed wrong fd in connection_handler() in server.c.

Do replace sv_socket_desc with newclient.client_fsd because accept return FD which is used for communication purpose, sv_socket_desc is a socket for listen new connection.

while(1){
        //printf("readbef\n");
        read_size = read(newclient.client_fsd, client_message, sizeof(client_message));
        printf("read_size = %ld\n", read_size);
        printf("client_message = %s\n", client_message);
        fflush(stdout);
        read_size = write(newclient.client_fsd, client_message, sizeof(client_message));
        int n;
        sscanf(client_message, "%d", &n);
        printf("recv from %s:%hu, seq = %d\n", client_addr, client_port_num, n);
        fflush(stdout);
    }
Comments