Bad Address when reading from sockets in C - c

i'm facing a problem that i m not able to debug (it seems), let me explain the situation. I have a server that do something and 10 clients to connect. To test the code i use the same machine to host and connect the server and clients. Now, it seems that sometimes i m able to connect a random number of clients, like 4 and during the fifth connection the client side, after a good connection with the server, when i try to read from socket it gives me Bad address.
Now this number seems pretty casual, infact this error on the client side is given sometimes during the third connection, sometimes during the sixth connection and rarely never when i try to connect 10 clients. anyway most of the time this error occurs during the fifth connection.
Here the codes of server and client
Client:
void contact_server(int sockfd, int buffer_size, int reading_pipe, int writing_pipe) {
float* buff = (float*)calloc(buffer_size,sizeof(float));
int ret = 0;
while(1){
ret = 0;
while(ret == 0){
if(sizeof(float)*buffer_size <= sizeof(float)*2048){
ret = read(sockfd, buff, sizeof(float)*buffer_size);
if(ret == -1){
printf("(from server) Error description is: %s\n",strerror(errno));
exit(0);
}
}
else{
long long unsigned int sum = 0;
ret = read(sockfd, buff, sizeof(float)*2048);
if(ret == -1){
printf("(from server) Error description is : %s\n",strerror(errno));
exit(0);
}
sum+=ret;
int count;
for(count = 2048; sum < sizeof(float)*buffer_size; count+=2048, sum+=ret){
if(buffer_size-count < 2048){
ret = read(sockfd, &buff[count], sizeof(float)*(buffer_size-count));
if(ret == -1){
printf("(from server) Error description is : %s\n",strerror(errno));
exit(0);
}
}
else{
ret = read(sockfd, &buff[count], sizeof(float)*2048);
if(ret == -1){
printf("(from server) Error description is : %s\n",strerror(errno));
exit(0);
}
}
}
}
}// waiting for server
ret = write(writing_pipe,buff, sizeof(float)*buffer_size);// writing to parent process
if(ret == -1){
printf("(to parent) Error description is : %s\n",strerror(errno));
exit(0);
}
ret = 0;
while(ret == 0){
ret = read(reading_pipe, buff, sizeof(float)*buffer_size);
if(ret == -1){
printf("(from parent) Error description is : %s\n",strerror(errno));
exit(0);
}
}// waiting for parent process
ret = write(sockfd,buff, sizeof(float)*buffer_size);// writing to server
if(ret == -1){
printf("(to server) Error description is : %s\n",strerror(errno));
exit(0);
}
}
free(buff);
}
/* See server.c for more specific details
*
*
* Inputs:
*
* # int port:= the port of the server
* # char* server_address:= the server address
* # int buffer_size:= the buffer size written by the server and parent process
* # int reading_pipe:= to read from parent
* # int writing_pipe:= to write to parent
* */
int run_client(int port, char* server_address, int buffer_size, int reading_pipe, int writing_pipe){
int sockfd, connfd;
struct sockaddr_in servaddr, cli;
int sockaddr_len = sizeof(struct sockaddr_in);
// socket create and varification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
fprintf(stderr,"Error: socket creation failed...\n");
exit(1);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(server_address);
servaddr.sin_port = htons(port);
// connect the client socket to server socket
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) {
printf("connection with the server failed...\n");
exit(0);
}
else
printf("connected to the server..\n");
// function for chat
contact_server(sockfd,buffer_size,reading_pipe,writing_pipe);
// close the socket
close(sockfd);
return 0;
}
Server:
void* server_thread(void* _args) {
// depacking args
thread_args_server* args = (thread_args_server*) _args;
float* buff = (float*)calloc(args->buffer_size,sizeof(float));
int ret;
while(1){
ret = 0;
while(ret == 0){
ret = read(args->reading_pipe, buff, sizeof(float)*args->buffer_size);
if(ret == -1){
printf("Error description is : %s\n",strerror(errno));
exit(0);
}
}// waiting for parent process
ret = write(args->client_desc,buff, sizeof(float)*args->buffer_size);// writing to client
if(ret == -1){
printf("Error description is : %s\n",strerror(errno));
exit(0);
}
ret = 0;
while(ret == 0){
if(sizeof(float)*args->buffer_size <= sizeof(float)*2048){
ret = read(args->client_desc, buff, sizeof(float)*args->buffer_size);
if(ret == -1){
printf("Error description is : %s\n",strerror(errno));
exit(0);
}
}
else{
long long unsigned int sum = 0;
ret = read(args->client_desc, buff, sizeof(float)*2048);
if(ret == -1){
printf("Error description is : %s\n",strerror(errno));
exit(0);
}
sum+=ret;
long long unsigned int count;
for(count = 2048;sum < sizeof(float)*args->buffer_size; count+=2048, sum+=ret){
if(args->buffer_size-count < 2048){
ret = read(args->client_desc, buff, sizeof(float)*(args->buffer_size-count));
if(ret == -1){
printf("Error description is : %s\n",strerror(errno));
exit(0);
}
}
else{
ret = read(args->client_desc, buff, sizeof(float)*2048);
if(ret == -1){
printf("Error description is : %s\n",strerror(errno));
exit(0);
}
}
}
}
}// waiting for client
ret = write(args->writing_pipe,buff, sizeof(float)*args->buffer_size);// writing to parent process
if(ret == -1){
printf("Error description is : %s\n",strerror(errno));
exit(0);
}
}
free(buff);
return NULL;
}
/* This function creates a server on your current ip address on the port: port,
* accept a maximum number of connections = max_num_conn, and create each thread per connection.
* each thread read a float vector from a client and writes on the writing_pipes[i] this vector, then
* wait for a float vector from reading_pipe[i] and send this vector to the client.
* The ideal situation is: client -> compute some instances of the mini batch, send to server the partial derivatives
* the thread of the client on the server side read these partial derivatives, send back to the father process with writing pipes,
* the parent process sum up all these partial derivatives, update the model, send back to the thread the model updated, the thread
* send to the client and the client goes on and compute again the new partial derivatives, and so on...
*
* Inputs:
*
* # int port:= the server port
* # int max_num_conn:= the maximum number of connections accepted by the server
* # int* reading_pipes:= a pipe writing for float vector to the thread
* # int* writing_pipes:= where the thread write its vector
* # int buffer_size:= the buffer of the vector
*
* */
int run_server(int port, int max_num_conn, int* reading_pipes, int* writing_pipes, int buffer_size, char* ip){
int socket_desc, client_desc,sockaddr_len = sizeof(struct sockaddr_in),c = 1;
int ret;
struct sockaddr_in server_addr;
struct sockaddr_in* client_addr;
struct sockaddr_in* client_addr2;
bzero(&server_addr, sizeof(server_addr));
inet_pton(AF_INET, ip, &(&server_addr)->sin_addr);
// socket creation
socket_desc = socket(AF_INET,SOCK_STREAM,0);
if(socket_desc == -1){
fprintf(stderr,"Error: can't create socket\n");
exit(1);
}
// Which connection can accept
server_addr.sin_addr.s_addr = INADDR_ANY;
// Ip family
server_addr.sin_family = AF_INET;
// Port
server_addr.sin_port = htons(port);
// Handling crash case to reuse the descriptor
ret = setsockopt(socket_desc,SOL_SOCKET,SO_REUSEADDR,&c,sizeof(int));
if(ret == -1){
fprintf(stderr,"Error: setsockopt failed..\n");
exit(1);
}
// Binding newly created socket to given IP and verification
if ((bind(socket_desc, (struct sockaddr *)&server_addr, sizeof(server_addr))) != 0) {
printf("socket bind failed...\n");
exit(0);
}
else
printf("Socket successfully binded..\n");
// listen on tot number of connections
ret = listen(socket_desc,max_num_conn);
if(ret == -1){
fprintf(stderr,"Error, listen failed\n");
exit(1);
}
int i = 0;
while(1){
client_addr = calloc(1,sizeof(struct sockaddr_in));
client_desc = accept(socket_desc,(struct sockaddr*)&client_addr,(socklen_t*)&sockaddr_len);
if((client_desc == 1 && errno == EINTR)) continue;
thread_args_server* thread = (thread_args_server*)malloc(sizeof(thread_args_server));
thread->idx = i;
thread->client_desc = client_desc;
thread->client_addr = client_addr;
thread->reading_pipe = reading_pipes[i];
thread->writing_pipe = writing_pipes[i];
thread->buffer_size = buffer_size;
pthread_t t;
pthread_create(&t,NULL,server_thread,thread);
pthread_detach(t);
printf("connected client id: %d\n",i);
i++;
}
pthread_exit(NULL);
return 0;
}
The error is given by ret = read(sockfd, &buff[count], sizeof(float)*(buffer_size-count)); on client side:
Thank you for the help

Related

client always gets connection refused when connect to server's new port socket

I'm designing a client/server system based on socket programming. Client first connects to a socket Sa with fixed port Pa on server, to get a new port number Pb for data transference. After getting Pb, close Sa and make a new socket Sb with Pb, but client always says 'connection refused'.
All above is in a child process fork() after Sa accept(), so what's the problem?
while (1)
{
struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
int new_server_socket = accept(server_socket,(struct sockaddr*)&client_addr,&length);
if ( new_server_socket < 0)
{
printf("Server Accept Failed!\n");
break;
}
printf("get new connection!\n");
int child_process_pid = fork();
if(child_process_pid == 0 )
{
close(server_socket);
int dataSock;
char buffer[BUFFER_SIZE];
bzero(buffer,BUFFER_SIZE);
length = recv(new_server_socket,buffer,BUFFER_SIZE,0);
if (length < 0)
{
printf("Server Recieve Data Failed!/n");
exit(1);
}
if(strcmp(buffer, "Get New Port\n") == 0)
{
srand((unsigned)time(NULL));
dataSock = (rand() % 10000) + 20000;
//printf("num is %d\n", num);
char sockNum[6];
sprintf(sockNum, "%d", dataSock);
bzero(buffer, BUFFER_SIZE);
strcpy(buffer, "The new port num is ");
strcat(buffer, sockNum);
strcat(buffer, " \n");
struct sockaddr_in data_server_addr;
bzero(&data_server_addr,sizeof(data_server_addr));
data_server_addr.sin_family = AF_INET;
data_server_addr.sin_addr.s_addr = htons(INADDR_ANY);
data_server_addr.sin_port = htons(dataSock);
int data_server_socket = socket(AF_INET,SOCK_STREAM,0);
if( data_server_socket < 0)
{
printf("Create Socket Failed!");
exit(1);
}
if( bind(data_server_socket,(struct sockaddr*)&data_server_addr,sizeof(data_server_addr)))
{
printf("Server Bind Port : %d Failed!", dataSock);
exit(1);
}
if ( listen(data_server_socket, LENGTH_OF_LISTEN_QUEUE) )
{
printf("Server Listen Failed!");
exit(1);
}
send(new_server_socket,buffer,BUFFER_SIZE,0);
close(new_server_socket);
while(1)
{
struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
int new_data_server_socket = accept(data_server_socket,(struct sockaddr*)&client_addr,&length);
if ( new_data_server_socket < 0)
{
printf("Server Data Connection Accept Failed!\n");
break;
}
printf("get new data connection!\n");
You shouldn't send the new port number until after the bind succeeds. And you don't need to use a randomized data port number at all. Just specify zero, do the bind(), call getsockname(), and see what port number the system allocated. Then send that to the client.

Why won't my server implementation run concurrently properly?

I am attempting to create a client/server system that can handle multiple concurrent connections using the unix system call fork.
The client enters a movie title, and the server will check if the movie was there or not. If it was there, it would tell the client the ranking, the name, and the box records.
looking at my forking implementation, the client asks for user input, however the program just simply goes pass it.
OUTPUT EXAMPLE:
connection made with client 127.0.0.1
PID IS 27270
--> all messages read - connection being closed
CLIENT: Please input an string: PID IS 0
At this line, CLIENT: Please input an string: PID IS 0, the user was suppose to input a string, however the program glances over it. How do I make the program take in the string from the client?
SERVER CODE:
int main()
{
int sock, clientsock, mlen, addrsize, msgct, chc, chct, pid;
struct sockaddr_in addr; //ipv4 address
char ch, buf[80];
/*
* Create a socket.
*/
sock = socket(AF_INET, SOCK_STREAM,0); //create socket (AF_NET shows its ipv4 internet connection, SOCK_STREAM shows its a tcp)
if (sock == -1)
{
perror("opening socket");
exit(-1);
}
//Bind socket to local address
/*
* Bind a name to the socket. Since the server will bind with
* any client, the machine address is zero or INADDR_ANY. The port
* has to be the same as the client uses.
*/
addr.sin_family = AF_INET;
addr.sin_port = htons (32351); //port number for local address
addr.sin_addr.s_addr = htonl (INADDR_ANY); //ip address (you can also hard code it)
if (bind(sock, (struct sockaddr *) &addr, //binding, first parameter : is the socket you created, &addr is the
sizeof (struct sockaddr_in)) == -1) //error checking
{
perror ("on bind");
exit (-1);
} //(at this moment we have binded socket)
/*
* Make the socket available for potential clients.
*/
//if there is connection or not?
if (listen(sock,1) == -1)
{
perror("on listen");
exit(-1);
}
//-------Text File Implementation-----------
FILE *fp;
char data[5][200];
char rank[5][2];
char name[5][255];
char value[5][100];
/* opening file for reading */
fp = fopen("movie.txt", "r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
}
fgets (data[0], 200, fp);
int i = 1;
while(fgets (data[i], 200, fp)!=NULL)
{
/* writing content to stdout */
sscanf(data[i],"%s %[^$] %s",rank[i],name[i],value[i]);
puts(data[i]);
i+=1;
}
//CODE DOES NOT IMPLEMENT AFTER THIS WHILE LOOP
//close the file
fclose(fp);
addrsize = sizeof(struct sockaddr_in);
//THIS WHILE LOOP IS NOT BEING IMPLEMENTED...
while(1)
{
clientsock = accept(sock, (struct sockaddr *) &addr, &addrsize);
if (clientsock == -1)//error checking
{
perror("on accept");
exit(-1);
}
printf("connection made with client ");
printf ("%s\n", inet_ntoa (addr.sin_addr)); //also print client address
/* Create child process */
pid = fork();
if (pid < 0)
{
perror("ERROR on fork");
exit(1);
}
if (pid == 0)
{
/* This is the client process */
close(sock);
bool exist = false;
mlen = recv (clientsock, buf, 80, 0);
if (mlen < 0)
{
perror("ERROR reading from socket");
exit(1);
}
int lenS;
int which;
for(int i = 1; i<5; i++)
{
printf("%s\n\n", name[i]);
char *pch = strstr(name[i],buf);
if(pch != NULL)
{
which = i;
exist = true;
puts("GOOD");
}
else
{
puts("bad");
}
}
if(exist)
{
//SEND TO CLIENT FROM HERE!
printf("%s\n", rank[which]);
printf("%s\n", name[which]);
printf("%s\n", value[which]);
lenS = strlen(name[which]);
send (clientsock, name[which], lenS+1, 0);
}
else
{
//SEND TO CLIENT FROM HERE!!!!
printf("NOT HERE ");
send (clientsock, "NOT HERE", 9, 0);
}
printf("Here is the message: %s\n",buf);
exit(0);
}
else
{
close(clientsock);
printf(" --> all messages read - connection being closed\n");
}
}
}
CLIENT CODE:
int main()
{
int sock, addrsize;
struct sockaddr_in addr;
unsigned int in_address;
char buf[80];
int mlen;
/*
* Open a socket for Internet stream services.
*/
sock = socket(AF_INET, SOCK_STREAM,0); //creating a socket to connect to server, AF_INET : ipv4 internet connection, SOCK_STREAM tcp
if (sock == -1)
{ perror("opening socket");
exit(-1);
}
addr.sin_family = AF_INET;
addr.sin_port = htons (32351); //port number has to be the same as the one from server
in_address = 127 << 24 | 0 << 16 | 0 << 8 | 1; //ip address, local host, since we are running client and server on the same computer, it needs to have the same ip address
addr.sin_addr.s_addr = htonl (in_address);
if (connect (sock, (struct sockaddr *) &addr, //binding
sizeof (struct sockaddr_in)) == -1)
{
perror("on connect");
exit(-1);
}
char word[100];
int len;
printf("CLIENT: Please input an string: ");
scanf("%s", word);
//printf("You entered: %s\n", word);
len = strlen(word);
send (sock, word, len+1, 0);
mlen = recv (sock, buf, 80, 0);
printf ("%s\n\n\n\n\n\n\n", buf);
/*
* Do a shutdown to gracefully terminate by saying - "no more data"
* and then close the socket -- the shutdown is optional in a one way
* communication that is going to terminate, but a good habit to get
* into.
*/
if (shutdown(sock, 1) == -1)
{
perror("on shutdown");
exit(-1);
}
printf ("Client is done\n");
close(sock);
}
You are running the client and server programs on the same machine, with the same controlling terminal. The server master process, its client-service subprocess(es), and the independent client process therefore may all write to that terminal. They run independently and concurrently, so their outputs can be mashed up.
The fact that the PID IS 0 message is emitted after the prompt does not indicate that the client program has skipped accepting input, which indeed, I don't see how it could do. The prompt and the PID message come from different processes.
It would make things clearer to launch the server process and the client process from separate (virtual) terminals, so that their output is not mixed.

Server is not accepting connection from Client side to read data from a file

I want to read a file on Server from the Client application on Linux. I have mentioned below my Server and Client application.
On Client side I open a file (which is necessary to my requirements).
The Client receive the data which I have written on the file. Now, I want to send the received data from Client to the Server side and get back the echo to the Client.
I am facing trouble with the Server to accept the Client connection. I am glad to have a solution, where I made mistake exactly. I also appreciate If I get the solution for the code. Thanks in advance.
Server.C
#include<stdio.h>
#define BufferLength 100
/* Server port number */
#define SERVPORT 3389
int main(int argc, char *argv[])
{
/* Variable and structure definitions. */
int sd, sd2, rc, length = sizeof(int);
int totalcnt = 0, on = 1;
char temp;
char buffer[BufferLength];
//char data[BufferLength];
struct sockaddr_in serveraddr;
struct sockaddr_in their_addr;
fd_set read_fd;
struct timeval timeout;
timeout.tv_sec = 15;
timeout.tv_usec = 0;
/*To read xillybus*/
// FILE *fp;
// fp = fopen("/dev/xillybus_read_8", "r");
// if(fp==NULL)
// {
// printf("Error file open\n");
// exit(-1);
// }
// else{
// printf("File found %s\n", fp);
// }
/* Get a socket descriptor */
if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Server-socket() error");
exit (-1);
}
else
{
printf("Server-socket() is OK\n");
}
/* Allow socket descriptor to be reusable */
if((rc = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) < 0)
{
perror("Server-setsockopt() error");
close(sd);
exit (-1);
}
else
{
printf("Server-setsockopt() is OK\n");
}
/* bind to an address */
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
printf("Using %s, listening at %d\n", inet_ntoa(serveraddr.sin_addr), SERVPORT);
if((rc = bind(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
{
perror("Server-bind() error");
close(sd);
exit(-1);
}
else
{
printf("Server-bind() is OK\n");
}
/* Up to 10 clients can be queued */
if((rc = listen(sd, 10)) < 0)
{
perror("Server-listen() error");
close(sd);
exit (-1);
}
else
{
printf("Server-Ready for client connection...\n");
}
/* accept() the incoming connection request. */
int sin_size = sizeof(struct sockaddr_in);
if((sd2 = accept(sd, (struct sockaddr *)&their_addr, &sin_size)) < 0)
{
perror("Server-accept() error");
close(sd);
exit (-1);
}
else
{
printf("Server-accept() is OK\n");
}
/*client IP*/
printf("Server-new socket, sd2 is OK...\n");
printf("Got connection from the client: %s\n", inet_ntoa(their_addr.sin_addr));
/* Wait for up to 15 seconds on */
/* select() for data to be read. */
FD_ZERO(&read_fd);
FD_SET(sd2, &read_fd);
rc = select(sd2+1, &read_fd, NULL, NULL, &timeout);
if((rc == 1) && (FD_ISSET(sd2, &read_fd)))
{
/* Read data from the client. */
totalcnt = 0;
while(totalcnt < BufferLength)
{
/* read() from client */
rc = read(sd2, &buffer[totalcnt], (BufferLength - totalcnt));
if(rc < 0)
{
perror("Server-read() error");
close(sd);
close(sd2);
exit (-1);
}
else if (rc == 0)
{
printf("Client program has issued a close()\n");
close(sd);
close(sd2);
exit(-1);
}
else
{
totalcnt += rc;
printf("Server-read() is OK\n");
}
}
}
else if (rc < 0)
{
perror("Server-select() error");
close(sd);
close(sd2);
exit(-1);
}
/* rc == 0 */
else
{
printf("Server-select() timed out.\n");
close(sd);
close(sd2);
exit(-1);
}
/* Shows the data */
printf("Received data from the client: %s\n", buffer);
printf("Server-Echoing back to client...\n");
/*Write function*/
rc = write(sd2, buffer, totalcnt);
if(rc != totalcnt)
{
perror("Server-write() error");
rc = getsockopt(sd2, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
/* Print out the asynchronously */
/* received error. */
errno = temp;
perror("SO_ERROR was: ");
}
else
{
printf("Server-write() is OK\n");
}
close(sd);
close(sd2);
exit(-1);
}
/******************************************/
close(sd2);
close(sd);
exit(0);
return 0;
}
Client.c
#include<stdio.h>
#define BufferLength 100
#define SERVER "00.00.00.00"
/* Server's port number */
#define SERVPORT 3389
/* set the server name in the #define SERVER ... */
int main(int argc, char *argv[])
{
/* Variable and structure definitions. */
int sd, rc, length = sizeof(int);
struct sockaddr_in serveraddr;
char buffer[BufferLength];
char server[255];
char temp;
int totalcnt = 0;
struct hostent *hostp;
//char data[500] = "Hello ravi !!! "; // writes data to the server
/*To open directory and read the xillybus*/
FILE *fp;
char s[100];
fp = fopen("/dev/xillybus_read_8", "r");
if(!fp)
return 1;
while(fgets(s,100,fp)!=NULL){
printf("%s ", s);
}
//fclose(fp);
/******************************************/
/* get a socket descriptor */
if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Client-socket() error");
exit(-1);
}
else
{
printf("Client-socket() OK\n");
}
/*If the server hostname is supplied*/
if(argc > 1)
{
/*Use the supplied argument*/
strcpy(server, argv[1]);
printf("Connecting to the server %s, port %d ...\n", server, SERVPORT);
}
else
{
/*Use the default server name or IP*/
strcpy(server, SERVER);
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);
}
if((serveraddr.sin_addr.s_addr = inet_addr(server)) == (unsigned long)INADDR_NONE)
{
/* get host address */
hostp = gethostbyname(server);
if(hostp == (struct hostent *)NULL)
{
printf("HOST NOT FOUND --> ");
/* h_errno is usually defined */
/* in netdb.h */
printf("h_errno = %d\n",h_errno);
printf("---This is a client program---\n");
printf("Command usage: %s <server name or IP>\n", argv[0]);
close(sd);
exit(-1);
}
memcpy(&serveraddr.sin_addr, hostp->h_addr, sizeof(serveraddr.sin_addr));
}
/* connect() to server. */
if((rc = connect(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
{
perror("Client-connect() error");
close(sd);
exit(-1);
}
else
{
printf("Connection established...\n");
printf("Sending some string to the server %s...\n", server);
}
/* Write() some string to the server. */
//rc = write(sd, data, sizeof(data));
rc = write(sd,fp, sizeof(fp)); // here is my write function
if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
/* Print out the asynchronously received error. */
errno = temp;
perror("SO_ERROR was");
}
close(sd);
exit(-1);
}
else
{
printf("Client-write() is OK\n");
printf("String successfully sent \n");
printf("Waiting the %s to echo back...\n", server);
}
totalcnt = 0;
/* Read data from the server. */
while(totalcnt < BufferLength)
{
rc = read(sd, &buffer[totalcnt], BufferLength-totalcnt); //&buffer[totalcnt],BufferLength-totalcnt
if(rc < 0)
{
perror("Client-read() error");
close(sd);
exit(-1);
}
else if (rc == 0)
{
printf("Server program has issued a close()\n");
close(sd);
exit(-1);
}
else
{
totalcnt += rc;
}
}
printf("Client-read() is OK\n");
printf("Echoed data from the server: %s\n", buffer); //data ->buffer
/* Close socket descriptor from client side. */
close(sd);
exit(0);
return 0;
}
In you client.c program, you try to send a FILE* to the server. What you are sending is the address of the file descriptor in client program and not the text contained in the file.
You send only 4 or 8 bytes (depending on architecture 32 or 64 bits), while server waits for at least 100 bytes before echoing anything. So both programs do exactly what you programmed - but not what you expected.
To send the content of a file, you read the file in a char array and send the char array. You can iterate over the file reading one buffer at a time and sending the buffer. But there is no magic allowing to send a whole file.

How to properly terminate a pthread?

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.

server receives data from multiple client and store in seperate file at same time in linux using c by threading

I have a server and two client.I want to store data in different file coming from clients at a same time.
Presently I'm storing data in a same file coming from two client.And after one client send the data, second starts to send.
I want that two client send the data at same time.
Anyone can help me...
server.c
void *function1(void *ptr);
typedef struct{
int port_id;
int thread_id;
}conn_id;
int main(int argc, char *argv[])
{
conn_id conn_id1[2];
conn_id1[0].port_id=7350;
conn_id1[0].thread_id=1;
conn_id1[1].port_id=7351;
conn_id1[1].thread_id=2;
conn_id* conn_ptr;
pthread_t thread[2];
int index=0;
for(index=0;index<2;index++){
conn_ptr=&conn_id1[index];
pthread_create(&thread[index],NULL,&function1,(void*)conn_ptr);}
pthread_join(thread[0],NULL);
pthread_join(thread[1],NULL);
return 0;
}
void *function1( void *ptr)
{
//Declaring process variables.
int server_sockfd, client_sockfd;
int server_len ;
int rc ;
conn_id* conn_ptr;
conn_ptr = (conn_id*)ptr;
unsigned client_len;
char revbuf[LENGTH];
struct sockaddr_in server_address;
struct sockaddr_in client_address;
//Remove any old socket and create an unnamed socket for the server.
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htons(INADDR_ANY);
server_address.sin_port = htons(conn_ptr->port_id);
server_len = sizeof(server_address);
bzero(&(server_address.sin_zero), 8);
rc = bind(server_sockfd, (struct sockaddr *) &server_address, server_len);
printf("RC from bind = %d\n", rc ) ;
//Create a connection queue and wait for clients
rc = listen(server_sockfd, 5);
printf("RC from listen = %d\n", rc ) ;
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd, (struct sockaddr *) &client_address, &client_len);
printf("after accept()... client = %s\n", inet_ntoa(client_address.sin_addr)) ;
while(1)
{
/*Receive File from Client */
char* fr_name = "/home/server/Desktop/fr_client.dat";
FILE *fr = fopen(fr_name, "a");
if(fr == NULL)
printf("File %s Cannot be opened file on server.\n", fr_name);
else
{
bzero(revbuf, LENGTH);
int fr_block_sz = 0;
while((fr_block_sz = recv(client_sockfd, revbuf, LENGTH, 0)) > 0)
{
int write_sz = fwrite(revbuf, sizeof(char), fr_block_sz, fr);
if(write_sz < fr_block_sz)
{
error("File write failed on server.\n");
}
bzero(revbuf, LENGTH);
if (fr_block_sz == 0 || fr_block_sz != 512)
{
break;
}
}
if(fr_block_sz < 0)
{
if (errno == EAGAIN)
{
printf("recv() timed out.\n");
}
else
{
fprintf(stderr, "recv() failed due to errno = %d\n", errno);
exit(1);
}
}
printf("Ok received from client!\n");
fclose(fr);
}
/* Call the Script */
system("cd ; chmod +x script.sh ; ./script.sh");
/* Send File to Client */
char* fs_name = "/home/server/Desktop/output.txt";
char sdbuf[LENGTH]; // Send buffer
printf("[Server] Sending %s to the Client...", fs_name);
FILE *fs = fopen(fs_name, "r");
if(fs == NULL)
{
fprintf(stderr, "ERROR: File %s not found on server. (errno = %d)\n", fs_name, errno);
exit(1);
}
bzero(sdbuf, LENGTH);
int fs_block_sz;
while((fs_block_sz = fread(sdbuf, sizeof(char), LENGTH, fs))>0)
{
if(send(client_sockfd, sdbuf, fs_block_sz, 0) < 0)
{
fprintf(stderr, "ERROR: Failed to send file %s. (errno = %d)\n", fs_name, errno);
exit(1);
}
bzero(sdbuf, LENGTH);
}
printf("Ok sent to client!\n");
close(client_sockfd);
printf("[Server] Connection with Client closed. Server will wait now...\n");
while(waitpid(-1, NULL, WNOHANG) > 0);break;
}
}
If you want to receive data simultaneously from multiple clients, basically, you have 2 choices:
Still use synchronous socket I/O, but in multiple threads, each thread communicates with one client, and writes data into a shared file handle, which is protected by a mutex lock.
Use asynchronous socket I/O, single thread. In a loop, you should first call select() on multiple sockets, and do I/O once there're events on the sockets. In this case, you don't need mutex on the file handle.
Another way is to create a thread for each connection and create a file for each thread using the client-ip and port to name the file. Later you can combine these files.

Resources