2013-03-10 61 views
0

我在从服务器上的客户端读取数据时遇到问题。读取()函数将在所有数据被采集并且等待更多数据之后始终冻结(阻止),这对我来说是不理想的。从套接字冻结读取

服务器程序:

soc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    struct sockaddr_in sin; 
    sin.sin_family = AF_INET; 
    sin.sin_port = htons(port); 
    sin.sin_addr.s_addr = INADDR_ANY; 
    bind(soc, (struct sockaddr*) &sin, sizeof(sin)); 

    if (listen(soc, MAX)) 
     return; 

    int socc;    // socket for clinet  
    while (1) { 
     if ((socc = accept(soc, (struct sockaddr *) &sin, sinlen)) < 0) 
     break; 
     while ((result = read(socc, pointer, SIZE)) > 0) { 
     // after the data are readed, read function will block 
     } 
     // do some stuff and write reply to client => will never done 
    } 

客户端程序:

... 
    soc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) 
    struct sockaddr_in socketAddr; 
    socketAddr.sin_family = AF_INET; 
    socketAddr.sin_port = htons(port); 
    memcpy(&(socketAddr.sin_addr), host->h_addr, host->h_length); 
    if (connect(soc, (sockaddr *)&socketAddr, sizeof(socketAddr)) == -1) 
     return; 
    if (write(soc, req.c_str(), strlen(req.c_str())) < 0) 
     return; 

的主要问题是,我不知道有多少数据将客户端发送到服务器,因此服务器应阅读所有来自套接字的数据,在没有任何事情发生之后,离开读取周期。但服务器读取整个消息(例如30字节)并等待更多(但不会再有更多消息)。由于客户端正在等待服务器的回复,因此套接字仍处于打开状态。

+0

您是否知道*如果客户端将数据发送到服务器?你有没有考虑一个'select()'循环而不是阻塞IO调用? – WhozCraig 2013-03-10 05:42:31

回答

2

正如前面所述使用非阻塞或添加RCV_TIMEOUT到插座。

struct timeval tv; 

tv.tv_sec = 30; /* 30 Secs Timeout */ 

setsockopt(sockid, SOL_SOCKET, SO_RCVTIMEO,(struct timeval *)&tv,sizeof(struct timeval)); 
+0

就我而言,这种解决方案更好,因为当我尝试发送大约30MB的文件时,select命令会导致巨大的减速。在套接字创建语句之后简单地添加你的代码就完成了。 – Alex 2015-06-18 11:57:12