2012-03-03 82 views
0

那Im上工作(这是一个Unix下C多线程非块套接字服务器)需要从客户端接收一个文件,并将其广播到连接到所有其他客户端的服务器服务器。非块插座连续文件传输

一切都在那不好受林来确定当一个文件被转移做...因为即时通讯使用时遇到的问题文件传输的recv返回-1时有时无堵塞插座进出口异常的工作(这我是假设是文件的结尾),那么下一次多个字节进来。

我尝试破解整个事情将“END”在流的末尾。但是,有时在一行中发送多个文件时,“END”与下一个文件的开头是同一个recv缓冲区的一部分。甚至是最糟糕的,有时我结束了与EN和下传的d进来完成一个缓冲。

什么是避免上述情况的最好办法,我真的不希望每一次我从套接字循环中接收了一些字节的整个累积缓冲区,以检查“END”是否是它的一部分,然后适当地剪切......我确定有更好的解决方案来解决这个问题吗?

在此先感谢!

+2

在发送数据本身之前,为什么不先发送文件大小? – 2012-03-03 07:12:12

回答

0

最simpe情况EJP指的是,在那里你把插座的另一端作为档案结尾关闭的情况下,可能看起来像以下:

{ 
    ssize_t sizeRead = 0; 

    while (sizeRead = recv(...)) { 
    if (0 > sizeRead) { /* recv() failed */ 
     if ((EGAGAIN == errno) ¦¦ (EWOULDBLOCK == errno)) { /* retry the recv() on those two kinds of error */ 
     usleep(1) /* optional */ 
     continue; 
     } 
     else 
     break; 
    } 

    ... /* process the data read ... */ 
    } 

    if (0 > sizeRead) { 
    /* There had been an error during recv() */ 
    } 
} 
2

如果recv()返回-1这是一个错误,您需要检查errno。最有可能的是它是EAGAINEWOULDBLOCK,这意味着当前没有数据在套接字接收缓冲区中。所以你需要重新选择()。

recv()返回同行已断开连接的插座和传输完成。

+0

重新选择你的意思是什么?我不想在等待状态期间阻塞线程循环...我需要同时处理其他客户端的传输... – McBob 2012-03-03 07:20:24

+0

@McBob我不明白。使用非阻塞I/O的全部原因是您可以在一个线程中处理多个客户端。这就是select()的用途。当'recv()'返回-1并且'errno'为'EAGAIN/EWOULDBLOCK'时,你继续处理下一个准备好的FD。当你不在时,重新选择。 – EJP 2012-03-03 08:47:05

1

信令结束某个字节序列的文件不可靠,该文件可能包含该序列。首先发送文件长度 - 如果允许大文件传输,则使用4字节或8字节,使用网络字节顺序。

if ((n = read(..., filelen)) > 0) { 
    filelen -= n; 
}