Why won't my server implementation run concurrently properly? - c

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.

Related

Bad Address when reading from sockets in 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

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.

return from read in connected udp sockets in c

i programming UDP client/Server model and the main functionaly for this app is client insert the directory path then the server will retrun the contents of supplied directory to the client, so this Client code :
#include "cliHeader_UDP.h"
int
main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
/*Error checking for providing appropirate port# */
if(argc<3 )
err_quit("Error,no port provided, please enter the port#:22011 \n");
portno=atoi(argv[2]);
for(;;)
{
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(portno);
Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr));
}
exit(0);
}
**//and here is the dg_cli implemntation :**
void
dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
{
int n;
char sendline[MAXLINE], recvline[MAXLINE + 1];
Connect(sockfd, (SA *) pservaddr, servlen);
for(;;)
{
bzero(&sendline, sizeof(sendline));
printf("please enter Directory Name :\n");
Fgets(sendline, MAXLINE, fp);
/*To check if the supplied name ended with \n in sendline buffer */
if((p = strchr(sendline, '\n'))) *p = 0;
write(sockfd, sendline, strlen(sendline));
printf("test for write\n");
**Line 31.......:** while ( (n=read(sockfd, recvline, MAXLINE)) )
{
if(n<0)
perror("Error");
printf("recvline is: %s\n",recvline);
printf("n========%d\n",n);
}
printf("exit from read While\n");
recvline[n] = 0; /* null terminate */
}
}
the problem in Line 31... is the 1st time run as i wanted client insert DIR path so the server will return the contents of the path ,but when the user need to insert again the path ,its still blocking in read in the for loop and does not return from for loop ,
so how to put condtion when the contents of buffer ended return from for loop like EOF in TCP
As you noticed there's no concept of "connection" in UDP - even if you called connect(2) - so there's no way for read to return 0 when the communication is over. There are ways to fix this:
Have the server send a 0-length message when the output is over or some other special marker
Have the client analyze the input and somehow detect it is over
Both these methods are a little bit fragile in practice: imagine what happens if the "output is over" message gets lots. So you'll also have to provision for that case and maybe add a timeout (look for SO_RCVTIMEO for example).
i tried some thing like that have a look :
part of code at server side:
//at server side Read the directory contents
printf("The contents of [%s] is :\n",mesg);
bzero(&mesg, sizeof(mesg));
while( (dptr = readdir(dp)) !=NULL )
{
printf(" \n[%s] \t",dptr->d_name);
//report(dptr->d_name, &status_buf);
sprintf(mesg,"%s",dptr->d_name);
if((dptr = readdir(dp)) ==NULL)
{
bzero(&mesg, sizeof(mesg));
sprintf(mesg,"%c",'!');
Sendto(sockfd, mesg, sizeof(mesg), 0, pcliaddr, len);
}
Sendto(sockfd, mesg, sizeof(mesg), 0, pcliaddr, len);
}
// Close the directory stream
closedir(dp);
//and at the client side :
flag=1;
while ( (n=read(sockfd, recvline, MAXLINE)) )
{
if(n<0)
perror("Error");
printf("recvline is: %s\n",recvline);
flag=flag+1;
printf("Flag now is :%d\n",flag);
printf("n========%d\n",n);
bzero(&recvline, sizeof(recvline));
if(recvline[0]=='!')
return;
}

maximum data that can be sent through a port-socket

i have implemented a program which takes input from client, performs operation on server and writes the data to the client. ls command is what i have chosen for example.
Now my doubt is,
1) what if the input is very huge in bytes??
2) what is the maximum data that can be sent through a socket port??
client.c
int main()
{
FILE *fp;
int servfd, clifd;
struct sockaddr_in servaddr;
struct sockaddr_in cliaddr;
int cliaddr_len;
char str[4096], clientip[16];
int n;
servfd = socket(AF_INET, SOCK_STREAM, 0);
if(servfd < 0)
{
perror("socket");
exit(5);
}
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERVPORT);
servaddr.sin_addr.s_addr = inet_addr(SERVIP);
if(bind(servfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
perror("bind");
exit(0);
}
listen(servfd, 5);
printf("Server is waiting for client connection.....\n");
while(1)
{
cliaddr_len=sizeof(cliaddr);
clifd = accept(servfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
strcpy(clientip, inet_ntoa(cliaddr.sin_addr));
printf("Client connected: %s\n", clientip);
if(fork() == 0)
{
close(servfd);
while(1)
{
n = read(clifd, str, sizeof(str));
str[n] = 0;
if(strcmp(str, "end") == 0)
{
printf("\nclient(%s) is ending session and server is waiting for new connections\n\n", clientip);
break;
}
else if (strcmp(str, "ls") == 0) {
system("ls >> temp.txt");
fp = fopen("temp.txt", "r");
fread(str, 1, 500, fp);
remove("temp.txt");
}
else
printf("Received from client(%s): %s\n", clientip, str);
write(clifd, str, strlen(str));
}
close(clifd);
exit(0);
}
else
{
close(clifd);
}
}
}
server.c
int main()
{
int sockfd;
struct sockaddr_in servaddr;
char str[500];
int n;
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERVPORT);
servaddr.sin_addr.s_addr = inet_addr(SERVIP);
if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
printf("Could not connect to server: %s\n", strerror(errno));
exit(1);
}
while(1)
{
printf("Enter message: ");
scanf(" %[^\n]", str);
write(sockfd, str, strlen(str));
if(strcmp(str, "end") == 0)
break;
n = read(sockfd, str, sizeof(str));
str[n] = 0;
printf("Read from server: %s\n", str);
}
close(sockfd);
}
As for your question no 1. the huge data is broken in many packets & then sent packet by packet its done by OS internally. & the one packet size depends on your system OS(you can change it.It is called MTU maximum transfer unit).
& for your question no 2. the data send by a socket port may be infinite coz as long as u wish to send data it will send. there is no limit.!!!
Q: What if the input is very huge in bytes?? What is the maximum data that can be sent through a socket port??
A: There is no limit on the size of a TCP/IP stream. In theory, you could send and receive an infinite number of bytes.
... HOWEVER ...
1) The receiver must never assume is will ever get all the bytes at once, in a single read. You must always read socket data in a loop, reading as much at a time as you wish, and appending it to the data you've already read.
2) You can send a "large" amount of data at once, but the OS will buffer it behind your back.
3) Even then, there's an OS limit. For example, here the maximum send buffer size is 1 048 576 bytes.:
http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom.ibm.ztpf-ztpfdf.doc_put.cur%2Fgtpc2%2Fcpp_send.html
If you need to send more, you must send() in a loop.
PS:
As Anish recommended, definitely check out Beej's Guide to Network programming:
http://beej.us/guide/bgnet/output/html/multipage/

Socket programming: recv/read issue

EDIT: the code below has been fixed to receive and send properly AND to account for the actual bytes of messages sent annd recieved (latter thanks to EJP)
I'm programming with C in Unix.
I have server and client that are supposed to exchange msgs. While client seems to send messages fine, server doesn't receive the messages the client is sending. I've tried using recv() and read() (i know they are practically the same thing but with extra flags on recv()) but I have no luck and I'm not really sure what the problem really is.
I put sleep(3) in the client code after every time it sends a message but i see that once client and server are connected, server immediately closes without waiting for the incoming messages. What am i doing wrong?
This is the client-side code:
#define SERVER_TCP_PORT 11112
#define MAX_DATA_SIZE 500
int main(int argc, char * argv[])
{
int sockfd;
char * host;
char msg[MAX_DATA_SIZE];/* = "get my msg!\n";*/
int msg_len;
struct hostent * hp;
struct sockaddr_in client_address, server_address;
printf("y halo thar\n");
// looking up from the host database
if (argc == 2)
host = argv[1];
else
exit(1);
printf("sdf\n");
hp = gethostbyname(host);
if (!hp)
exit(1);
printf("host found\n");
// setting up address and port structure information
bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
server_address.sin_family = AF_INET;
bcopy(hp->h_addr, (char *) &server_address.sin_addr, hp->h_length);
server_address.sin_port = htons(SERVER_TCP_PORT);
printf("set\n");
// opening up socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
exit(1);
printf("opened\n");
// connecting
if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
exit(1);
printf("connected\n");
int i;
for (i = 0; i < MAX_DATA_SIZE; ++i)
{
msg[i] = '.';
}
msg[MAX_DATA_SIZE-1] = '\0';
for(i = 0; i < 11; i++)
{
// send message to connected socket
msg_len = write(sockfd, msg, MAX_DATA_SIZE);
if(msg_len < 1)
printf("notsent\n");
else
printf("%i bytes sent\n", msg_len);
// recieve messages from connected socket
msg_len = read(sockfd, msg, MAX_DATA_SIZE);
if (msg_len < 1)
printf("not recieved\n");
else
{
printf("%i bytes received\n", msg_len);
printf(msg);
printf("\n");
}
}
// close connection
close(sockfd);
printf("closed\n");
}
and this is the server side
#define SERVER_TCP_PORT 11112
#define MAX_DATA_SIZE 500
int main()
{
printf("o halo thar\n");
int sockfd, new_sockfd;
int client_addr_len;
char msg [MAX_DATA_SIZE];
int msg_len;
char got_msg [11] = "got ur msg\0";
struct sockaddr_in server_address, client_address;
// setting up address and port structure information
bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(SERVER_TCP_PORT);
// opening up socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
exit(1);
printf("socket is opened\n");
// binding
if (bind(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
exit(1);
printf("socket is bound\n");
// listening
listen(sockfd,5);
printf("listening\n");
// block and wait for an incoming connection
client_addr_len = sizeof(client_address);
new_sockfd = accept(sockfd, (struct sockaddr *) &client_address, &client_addr_len);
if (new_sockfd < 0)
exit(1);
printf("accepted\n");
int i;
for( i = 0; i < 11; i++)
{
// recieve messages from connected socket
printf("waiting\n");
msg_len = read(new_sockfd, msg, MAX_DATA_SIZE);
if (msg_len < 1)
{
printf("no msg recieved\n");
}
else
{
printf("bytes recieved: %i\n", msg_len);
}
// send message to connected socket
msg_len = write(new_sockfd, got_msg, sizeof(got_msg));
if (msg_len < 1)
printf("not sent\n");
else
printf("%i bytes sent\n", msg_len);
}
// close connection
close(sockfd);
printf("socket closed. BYE! \n");
}
In the server code, the problem is on this line:
msg_len = read(sockfd, msg, MAX_DATA_SIZE);
You are calling read on sockfd, but you need to call read or recv on new_sockfd (the socket returned by accept()). new_sockfd is the one that's connected to the client (sockfd is used to accept further connections - eg if another client connects).
You should read from the socket returned by accept.
Try to call read on the socket returned from accept.
Receiver Side:
while(1)
{
len=read(sd,buff,sizeof(buff));
if(len==0)
{
//End of File receving.
break;
}
else
{
st=fwrite(buff,sizeof(char),len,fp);
}
}
Send Side:
while(!feof(fp))
{
len=fread(buff,sizeof(char),MW,fp);
if(len==0)
{
//EOF
st=write(cd,&d,sizeof(int));
break;
}
else
{
st=write(cd,buff,len);
}
}
is the implementation based on stream or datagram?
there are some problem with your operation flow. the server might start to read before client send anything.
since client and server are separated, you can imagine them running concurrently.
right after your server side "accept" connection request, there might be possibly some handshake overhead occurs or network delays causing server app to execute ahead in time, attempt to extract data but meet with errors (no data received yet).
you can try this out by adding sleep in server code after accept connection, where client should have enough time to send the data.
another better solution is to make data retrieval cope with empty buffer or asynchronous read.

Resources