【发布时间】:2016-12-07 00:58:40
【问题描述】:
我正在尝试创建两个程序一个客户端和服务器,其中客户端打开一个套接字连接,然后将数据写入服务器,服务器在接受连接时会产生一个新线程,然后将其分离,以处理其余的读取/写。问题是,当我进行多次写入然后从客户端读取时,读取并没有得到正确的数据,但是在服务器端它打印出它发送了正确的数据。
这就是我的代码生成新线程的样子,以及我如何处理这些线程。
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 来调试网络代码。 Wireshark 当然会让你看到你发送的内容,你可以使用
nc作为一个已知的工作服务器和客户端,这样你就可以隔离你的服务器和客户端,减少你一次处理的变量数量。 -
不要在
accept()循环中调用listen()。在进入循环之前调用它一次。并且不需要malloc()你的套接字描述符。在使用它执行空终止操作之前,您不会空终止您的buffer,例如printf()和strcmp()。您也没有考虑到 TCP 是一种流传输,不能保证read()将接收完整的字符串,它有时可以(并且可能会)接收部分数据。您需要在发送端分隔命令并在读取端查找那些分隔符。 -
在客户端调用 read() 两次然后得到正确的数据。我将如何解释 TCP 是流传输这一事实,继续调用 read() 直到我得到非空响应?另外关于空终止字符,如果发送带有空终止字符的字符串,我是否需要在阅读后手动重新添加它?
标签: c multithreading sockets