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
Post a Comment