2016-03-30 8 views
0

ソケットを使用して小さなプログラムサーバークライアントを作成しました。私はそれが何をする必要があるのか​​、そのバグについて説明します。サーバーは新しいクライアント(ソケット)ごとにスレッドを割り当てません

アプリケーションには、クライアントのためのサーバーの魔法使いがあります。同時に最大6クライアントをサポートします。各クライアントサーバーは、DETASH_STATEでスレッドを起動し、次に戻ってきます。

クライアントはファイルのコンテキストをサーバーに送信します。私は願っています

.txtの「任意のランダムな文字列を」__ft_:サーバがクライアントから送信されたコンテンツを受信するなどユニークな名前で、ファイルに保存します

を(私は行ごとに送信することを選択しました)今まではすべて明らかです。

バグ: もし私がクライアントを起動したら、20回言いましょう。サーバー側には20のファイルがありません。時々私は10、場合によっては12,5,7(予測不可能)を持っています。これは、3つまたは4つまたは5つのクライアント(ここでは私は3-4-5ファイルが必要です)によって送信されたコンテンツを1つのファイルに書き込みます。私はどこにバグがあるのか​​、何が間違っているのか分からない。追加情報が必要な場合は教えてください。

これは、サーバーのコード(その一部)である:(iの問題であり、ここではないと思います)

/**********ASSING A PROTOCOL TO A SOCKET (BIND)************/ 

if(bind(sock_dest, (struct sockaddr *)&server,sizeof (server))<0) 
{ 
    printf("Bind failed\n"); 
    return 1; 
} 

/**********************************************************/ 

/*************** LISTEN FOR CONNECTIONS ********************/ 

listen(sock_dest,6); 
printf("Waiting for connections\n"); 

/**********************************************************/ 


/****ACCEPT CONNECTION AND MAKE ATHREAD FOR EVERY CLIENT***/ 
c = sizeof (struct sockaddr_in); 
pthread_t thread_id; 
pthread_attr_t attr; 
pthread_attr_init(&attr); 
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); 

while((client_socket = accept(sock_dest, (struct sockaddr *)&client, (socklen_t *) &c))) 
{ 
    printf("Connection accepted.\n"); 

    if(client_socket < 0) 
    { 
     printf("Accepting connection failed.\n"); 
     return 1; 
    } 

    if(pthread_create(&thread_id, &attr, connection_handler, (void*) &client_socket) < 0) 
    { 
     printf("Couldn't create a thread for the new client.\n"); 
     return 1; 
    } 
    else 
    printf("Handler assigned\n"); 
} 




return 0; 
} 


void *connection_handler (void *socket_dest) 
{ 
char *dest_file_name; 
char buffer[300]; 
int sock = *(int *) socket_dest; 
char *exit_signal="EXIT"; 

if((dest_file_name=create_random_name())==NULL) 
{ 
    printf("Generating a random name failed\n"); 
    return NULL; 
} 

int i=0; 
while(1) 
{ 
    while(i<299) 
    { 
     recv(sock,buffer+i,1,0); 
     if(buffer[i]=='\n') 
     { 
      i=0;   // setting i to 0 because next time when we read a path(string) it need to be stored from 0 pozition in array. 
      break; 
     } 
     ++i; 
    } 

    if((strcmp(buffer,exit_signal))==0) 
    { 
     printf("Exit signal received.\n"); 
     return NULL; 
    } 

    if((write_line_in_file(buffer,dest_file_name))==1) 
    { 
     printf("Failed to write one of the lines in %s\n",dest_file_name); 
    } 


    printf("Linie primita:%s\n",buffer); 

    bzero(buffer,256); // put all bytes to 0 from buffer 
} 

return 0; 
} 



char *create_random_name(void) 
{ 
const char charset[] = "abcdefghijklmnopqrstuvwxyz"; 
char *file_name; 
int i=0; 
int key; 
struct stat stbuf; 
time_t t; 

while(1) 
{ 

    srand((unsigned) time(&t)); 

    if((file_name = malloc(16 * sizeof (char))) == NULL) 
    { 
     printf("Failed to alloc memory space\n"); 
     return NULL; 
    } 
    strcpy(file_name,"__ft_"); 
    for(i=5 ; i<11 ; i++) 
    { 
     key = rand() % (int)(sizeof(charset)-1); 
     file_name[i]=charset[key]; 
    } 
    strcat(file_name,".txt"); 
    file_name[15] = '\0'; 
    if(stat(file_name,&stbuf)==-1) 
    { 
     break; 
    } 
} 
return file_name; 
} 

/************* RETURN 0 IF SUCCES AND 1 IF FAILS ***********/ 

int write_line_in_file(char *line,char *file_name) 
{ 
FILE *file; 
if((file=fopen(file_name, "a")) == NULL) 
{ 
    printf("Can't open %s.\n"); 
    return 1; 
} 
fprintf(file,"%s",line); 
fclose(file); 
return 0; 
} 

そして、これは、クライアントコードです:

#include <stdio.h> 
#include <stdlib.h> 
#include<netdb.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <string.h> 




int main(int argc, char *argv[]) 
{ 
/***************CHECKING THE ARGUMENT*************/ 
if (argc < 2) 
{ 
    printf("Usage: %s hostname\n", argv[0]); 
    return 1; 
} 
/*************************************************/ 

int sock_dest; 
struct sockaddr_in server_addr; 
char line[300]; 

/******************CREATE SOCKET*****************/ 

sock_dest = socket(AF_INET, SOCK_STREAM, 0); 
if(sock_dest == -1) 
{ 
    printf("Couldn't create socket.\n"); 
    return 1; 
} 

struct hostent *server; 
server = gethostbyname(argv[1]); 

if (server == NULL) 
{ 
    printf("ERROR, no such host\n"); 
    return 1; 
} 

/***** SETTING FIELDS OF SERVER SOCKADDR_IN STRUCTURE *****/ 

bzero((char *) &server_addr, sizeof(server_addr)); 
server_addr.sin_family = AF_INET; 
bcopy((char *)server->h_addr,(char *)&server_addr.sin_addr.s_addr,server->h_length); 
server_addr.sin_port = htons (31000); 

/**********************************************************/ 

/*********TRYING TO CONNECT TO THE SERVER******************/ 


if (connect(sock_dest,(struct sockaddr *) &server_addr,sizeof(server_addr)) < 0) 
{ 
    printf("ERROR:(Can't connect to the server. Please check if it's online)\n"); 
    return 1; 
} 

/***********************************************************/ 

char path_read[200]; 
int read_len,n; 
FILE *f_read; 
char *exit_signal = "\nEXIT\0"; 
if((f_read=fopen("test.txt","r"))==NULL) 
{ 
    printf("Failed to open path.txt.\n"); 
    return 0; 
} 
while((fgets(path_read,200,f_read))!=NULL) 
{ 
    path_read[strlen(path_read)+1]='\n'; 
    n = write(sock_dest,path_read,strlen(path_read)); 
    if(n<0) 
     error("ERROR writing to socket"); 
    bzero(path_read,200); 
} 

n=write(sock_dest,exit_signal,strlen(exit_signal)); 
fclose(f_read); 
close(sock_dest); 
printf("All lines in the file were sent to the server.\nExiting...\n"); 

return 0; 
} 
+1

'create_random_name'関数が同じファイル名を1回以上生成しているかどうかを確認していません。 – Nadir

+0

は同じ名前を生成することが可能で、それが同じファイルに書き込むのはなぜですか? –

+0

可能性があります(その可能性は低いですが、そこにはあります)。既に存在するファイルの名前を返さないように変更してください。 – Nadir

答えて

1

です1つのバグ:

(void*) &client_socket 

最初に、void*にキャストする必要はありません。第2に、はローカル変数で、コンテキストとしてスレッドに渡すアドレスです。開始スレッドでは、引き続きその値を次の反復で上書きします。

+0

お時間をいただきありがとうございます。クライアント変数がローカル変数であると言うと、client_socketをどうすればいいですか? –

+0

最初に、サイトのガイドラインが実際に必要とするように、最小限の例を提供すれば、本当に役に立ちます。コンテキスト情報をスレッドに正しく渡すには、スレッドチュートリアルで説明するか、または表示する必要があります。これを修正するには、コンテキスト情報を動的に割り当てるか、整数値をvoidポインタ値として渡すことができます。 –

関連する問題