我正在用C构建服务器客户端模型。客户端连接到服务器并开始交换数据。但是,用户可以在程序中随时终止客户端,但不会通知服务器。即使在客户端关闭后,服务器也会继续发送该数据。 我的印象是,如果服务器无法发送数据,send函数将返回-1,但我的服务器程序只是停留在发送
if((byteSent = send(new_fd, fileContents, strlen(fileContents), 0)) == -1){ //
程序在上面一行暂停。
我如何克服这个问题?
//代码
exitT = 0;
//execution_count = 1;
for(i=0;i<execution_count;i++)
{
sleep(time_delay);
//getting the current time on the server machine
time_t t;
time(&t);
char *time=ctime(&t);
printf("The Execution time at server = %s\n",time);
system(exec_command);
/*Open the file, get file size, read the contents and close the file*/
// Open the file
fp = fopen(fileName,"r");
// Get File Size
fseek(fp,0,SEEK_END);
dataLength = ftell(fp);
rewind(fp);
fileContents = (char*)malloc(dataLength+1);
// Read File
fread(fileContents,1,dataLength,fp);
fileContents[dataLength] = '\0';
// Close file
fclose(fp);
printf("sockfd = %d \n",new_fd);
// send file length to client
rc=send(new_fd, &dataLength, sizeof(dataLength), 0) ;
printf("length of client data = %d \n",rc);
printf("sockfd = %d \n",new_fd);
// send time to client
rc=send(new_fd, time, strlen(time), 0) ;
printf("length of client time = %d \n",rc);
usleep(20000);
// Send file contents to Client
while(dataLength>0){
printf("sockfd = %d \n",new_fd);
if((byteSent = send(new_fd, fileContents, strlen(fileContents), 0)) == -1){
printf("bytes sent = %d \n",byteSent);
exitT = 1;
break;
}
dataLength-=byteSent;
}
//Delete the log file
sprintf(deleteCommand,"rm %s",fileName);
system(deleteCommand);
if(exitT == 1)
break;
}
bzero(fileName,sizeof(fileName));
bzero(exec_command,sizeof(exec_command));
bzero(deleteCommand,sizeof(deleteCommand));
//decClientNum();
kill(parent_id,SIGALRM);
close(new_fd); // parent doesn't need this
printf("STATUS = CLOSED\n");
exit(0);
}
由于
答案 0 :(得分:1)
我假设您正在为Linux或Posix系统编码。
当send之类的系统调用失败时,返回-1并且设置errno
;你很可能应该使用errno来找出它失败的原因。
您可以使用strace找出您的服务器或其他系统调用所执行的系统调用。当然,也可以使用gdb
调试器。
您可能需要多路复用输入或输出。系统调用poll,select(以及相关ppoll
和pselect
)。阅读例如select_tut(2)手册页。
您可能希望使用(或至少研究源代码)现有的面向事件的库,如libevent
,libev
等。(Gtk和Qt框架也提供了自己的,甚至可以在GUI应用程序之外使用。)
我强烈建议您阅读advanced unix programming和unix network programing(也许还有advanced linux programming)。
答案 1 :(得分:0)
也许您正在使用tcp协议,服务器正在等待ACK。如果您希望连接是异步的,请尝试使用udp。
答案 2 :(得分:0)
从手册页:send()中没有隐含传递失败的迹象。本地检测到的错误由返回值-1表示。
这样的事情可能有所帮助:http://stefan.buettcher.org/cs/conn_closed.html
答案 3 :(得分:0)
我认为我在派对上已经很晚了,但我认为这个答案可能对某人有所帮助。
如果发送套接字上没有空间来保存要传输的消息,并且套接字文件描述符没有设置O_NONBLOCK,则send()将阻塞,直到空间可用。
当send()函数卡住时,可能会出现这样的情况:TCP窗口大小已经变为0.当连接的另一端没有消耗接收到的数据时会发生这种情况。
可能存在这样的情况,接收端进程正在由GDB运行并且发生了段错误。
因此,接收器TCP窗口大小将继续减小,您可以发送数据直到它大于零。一旦它变为0,send()函数将永远停滞。
由于问题中提到的情况不是封闭连接的情况。当进程在封闭的TCP连接上写入某些内容时,它会收到SIGPIPE信号。 SIGPIPE的默认处理程序终止进程。因此,在一个封闭的连接场景中,如果您没有使用自己的SIGPIPE处理程序,那么只要在套接字上写入了某些内容,就应该通过默认处理程序终止进程。