sockets - C linux server blocking -


server:

#include<stdio.h> #include<string.h>    //strlen #include<sys/socket.h> #include<arpa/inet.h> //inet_addr #include<unistd.h>    //write #include<stdlib.h> #include<sys/types.h> #include<sys/socket.h> #include<sys/stat.h> #include<netinet/in.h> #include<fcntl.h> #include <netdb.h> #include <dirent.h> #include <stdbool.h> #include <string.h> #include "shared.h"  char **serverfoldertree; int serverfoldersnumber;  files *fls; int serverfilesnumber;  void getfolders() {     = 0;     serverfoldertree = allocatefoldertree();     serverfoldersnumber = getfoldertree(serverfoldertree, "", server_root); }  void getfiles() {     i=0;     fls = getfilelist(fls, "", server_root);         serverfilesnumber = i; }  int main() {     int socket_desc , client_sock , c , read_size;     struct sockaddr_in server , client;     char client_message[2000], tmp[2000];      //create socket     socket_desc = socket(af_inet , sock_stream , 0);     if (socket_desc == -1)     {         printf("could not create socket");     }      //prepare sockaddr_in structure     server.sin_family = af_inet;     server.sin_addr.s_addr = inaddr_any;     server.sin_port = htons( 8888 );      //bind     if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)     {         //print error message         perror("bind failed. error");         return 1;     }      //listen     listen(socket_desc , 3);      acceptnew:      //accept , incoming connection     printf("\nwaiting incoming connections...\n");     c = sizeof(struct sockaddr_in);      //accept connection incoming client     client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);     if (client_sock < 0)     {         perror("accept failed");         return 1;     }     printf("connection accepted\n");      //receive message client     while( (read_size = recv(client_sock , client_message , 2000 , 0)) > 0 )     {     if(!strcmp(client_message, folder_tree_req))//folder tree requested     {         printf("recieved: folder tree req\n");         getfolders();          //send folder tree nr         sprintf(tmp,"%d",serverfoldersnumber);         write(client_sock , tmp , strlen(tmp)+1);          //send folder tree elements         int i;         for(i=0;i<serverfoldersnumber;i++)         {         //strcpy(tmp, serverfoldertree[i]);          sprintf(tmp,"%s",serverfoldertree[i]);         printf("%s\n", tmp);         write(client_sock , tmp , 1000);         }     }     }      if(read_size == 0)     {         printf("client disconnected\n");         fflush(stdout);     //goto acceptnew;//listen connection     }     else if(read_size == -1)     {         perror("recv failed");     }      return 0; } 

client:

#include<stdio.h> //printf #include<string.h>    //strlen #include<sys/socket.h>    //socket #include<arpa/inet.h> //inet_addr #include<stdlib.h> #include<sys/types.h> #include<sys/socket.h> #include<sys/stat.h> #include<netinet/in.h> #include<fcntl.h> #include <netdb.h> #include <dirent.h> #include <stdbool.h> #include <string.h> #include "shared.h"  char **clientfoldertree, **serverfoldertree; int clientfoldersnumber, serverfoldersnumber;  files *fls; int clientfilesnumber;  void getfolders() {     = 0;     clientfoldertree = allocatefoldertree();     serverfoldertree = allocatefoldertree();     clientfoldersnumber = getfoldertree(clientfoldertree, "", client_root); }  void getfiles() {     i=0;     fls = getfilelist(fls, "", client_root);         clientfilesnumber = i; }  int main() {     int sock;     struct sockaddr_in server;     char message[1000] , server_reply[2000];     bool k=true;       //create socket     sock = socket(af_inet , sock_stream , 0);     if (sock == -1)     {         printf("could not create socket");     }      server.sin_addr.s_addr = inet_addr("127.0.0.1");     server.sin_family = af_inet;     server.sin_port = htons( 8888 );      //connect remote server     if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)     {         perror("connect failed. error");         return 1;     }      printf("connected\n");      //req folder tree     getfolders();      strcpy(message, folder_tree_req);     if( send(sock , message , strlen(message) , 0) < 0)     {          puts("send failed");          return 1;     }      //receive folder tree number     recv(sock , server_reply , 2000 , 0);     serverfoldersnumber = atoi(server_reply);      printf("server fld nr: %d\n", serverfoldersnumber);     //recieve folder tree     for(i=0;i<serverfoldersnumber;i++)     {     if(recv(sock , server_reply , 2000 , 0) < 0)     {       puts("recv failed");       break;     }      printf("got: %s\n", server_reply);     }      close(sock);     return 0; } 

the server says sent list (and prints correctly) on client side recieves foldernumber (printed , works it's 10) when reciving tree prints "got: " less 3 times.

what problem here?

you assuming call recv() load single, complete folder string server_reply buffer, ie. need call recv() many times there folder strings.

that not work.

tcp not know, or care, null-terminated c-strings. transfers octet/byte streams only. if, say, have 50 folder names take 8000 bytes, possible, (though unlikely), may have call recv() 8000 times data, each call returning 1 byte.

edit:

sending folders not problem - send how many strings, strings.

sending request server problem:

if( send(sock , message , strlen(message) , 0)

will not send null-terminator. works first-time side-effect of server buffer array being initialized 0.

receiving request @ server problem:

read_size = recv(client_sock , client_message , 2000 , 0)

may read of folder_tree_req, or 1 char of it, or in between.

receiving size @ client problem:

recv(sock , server_reply , 2000 , 0);

may return entire ascii number, or first character of it, or in between, or entire ascii number plus part/s of folder string/s.

write(client_sock , tmp , 1000);

will try send entire 1000 bytes, null-terminated folder name @ start , uninitialized/leftover bytes @ end.

..and on.

you should fix code makes no assumptions messages longer 1 byte.

you should fix code not depend upon complete, null-terminated strings being transferred.

you should fix code not matter if data sent x send() calls received in 1 recv() call, x recv() calls or >x recv() calls.

sorry if seems messy, that's life tcp. if don't lock cannot go wrong, screw up, on else's installation, if seem work ok in testing.


Comments

Popular posts from this blog

basic authentication with http post params android -

vb.net - Virtual Keyboard commands -

How to get multiresult with multicondition in Sql Server -