我想創建兩個程序的客戶端和服務器,其中客戶端打開套接字連接,然後寫入數據到服務器誰接受連接產生一個新的線程,然後分離它,處理其餘的讀/寫道。問題在於,當我進行多次寫入時,從客戶端讀取的讀取沒有得到正確的數據,但是在服務器端,它會打印它發送正確的數據。使用線程來處理來自套接字的多個讀取/寫入?
這是我的代碼看起來像生成新線程,以及我如何處理這些線程。
while(1){
listen(sockfd,5);
// determine the size of a clientAddressInfo struct
clilen = sizeof(clientAddressInfo);
int *newsockfd = malloc(sizeof(int));
// block until a client connects, when it does, create a client socket
*newsockfd = accept(sockfd, (struct sockaddr *) &clientAddressInfo, &clilen);
// if the connection blew up for some reason, complain and exit
if (*newsockfd < 0){
error("ERROR on accept");
}
connection_args *args = malloc(sizeof(connection_args));
args->file_descrp = newsockfd;
pthread_t tid;
pthread_create(&tid,NULL, handle_connect, args);
}
void * handle_connect(void* args){
connection_args* connect_arg = (connection_args*)args;
pthread_detach(pthread_self());
int n = -1;
char buffer[256];
bzero(buffer,256);
//while not close;
while(1){
// try to read from the client socket
n = read(*connect_arg->file_descrp,buffer,255);
printf("input: %s\n", buffer);
// if the read from the client blew up, complain and exit
if (n < 0){
error("ERROR reading from socket");
}
int fd;
if(strcmp("open",buffer) == 0){
fd = open("file.txt",0);
bzero(buffer,256);
sprintf(buffer,"%d",fd);
}else if(strcmp("read",buffer) == 0){
char *read_buffer = malloc(sizeof(char)*256);
bzero(read_buffer,256);
fd = read(get_filedescrp(),read_buffer,30);
bzero(buffer,256);
sprintf(buffer,"%s,%d",read_buffer,fd);
}else if(strcmp("close",buffer) == 0){
break;
}
printf("buffer_send: %s\n",buffer);
// try to write to the client socket
n = write(*connect_arg->file_descrp,buffer,sizeof(buffer));
// if the write to the client below up, complain and exit
if (n < 0){
printf("here!!\n");
error("ERROR writing to socket");
}
bzero(buffer,256);
}
printf("Left thread\n");
return NULL;
}
就在一般情況下,我推薦使用Wireshark和[Netcat](https://linux.die.net/man/1/nc)來調試網絡代碼。 Wireshark當然會讓你看到你發送的內容,並且你可以使用'nc'作爲一個已知的服務器和客戶端,這樣你就可以隔離你的服務器和客戶端,從而減少你一次執行的變量數量。 – yano
不要在'accept()'循環中調用'listen()'。在進入循環之前調用它一次。並且不需要'malloc()'你的套接字描述符。並且,在執行以null結尾的操作之前,您不是空終止您的「緩衝區」,如'printf()'和'strcmp()'。你也沒有考慮到TCP是一個流式傳輸,並不能保證'read()'會接收完整的字符串,它可以(也可能)有時會接收部分數據。您需要在發送端分隔您的命令,並在讀取端查找這些分隔符。 –
在客戶端調用read()兩次,然後獲取正確的數據。我如何說明TCP是一個流式傳輸,在我得到一個非空響應之前一直調用read()?關於空終止字符,如果一個字符串與空終止字符一起發送,我需要手動重新添加它後,我讀? – user1457388