[英]C: Data forwarding server using epoll ET fills the send buffer
我有以下情况。 我的服务器从远程服务器(fd_server)接收数据,并将其转发到客户端(fd_client)。 我正在使用边缘触发的epoll,以便可以处理多个客户端和多个服务器连接。
程序:
细节:
我的服务器连接到远程服务器后,将fd_server添加到带有EPOLLIN标志的epoll控件中。 服务器等待事件。
当epoll_wait返回可读的fd_server时,我进入下面显示的循环。
经过一些读/写后,我的sctp_sendmsg返回EAGAIN,这意味着sctp发送缓冲区已满。 如何处理这种情况而又不会丢失已经从fd_server套接字读取的数据?
是否可以事先知道要发送多少数据,所以我只能读取正确的数据量?
while(1){
N = recv(fd_server,buf, sizeof buf,0);
if (N == -1){
/* If errno == EAGAIN, that means we have read all
data. So go back to the main loop. */
if (errno != EAGAIN){
perror ("tcp_recv error");
}
break;
}
if(N == 0){
/* End of file. The remote has closed the
connection. */
close(fd_server);
break;
}
pos = 0;
while(pos < N){
got = sctp_sendmsg(fd_client, &buf[pos], N-pos, to, tolen, 0, 0, stream, 0, 0);
if(got<=0){
if (errno == EAGAIN){
//what to do?
}else{
perror("tcp to sctp send error");
}
}
else{
pos += got;}
}
}
经过一些读/写后,我的sctp_sendmsg返回EAGAIN,这意味着sctp发送缓冲区已满。 如何处理这种情况而不会丢失从fd_server套接字读取的数据?
您需要为每个fd_client套接字保留某种“上下文”(数据结构)。 对于连接到服务器的每个新客户端套接字,创建“连接状态”结构的实例并将其存储在哈希表中。 这将类似于以下内容:
struct ConnectionState
{
int fd_client; // socket
uint8_t buffer[MAX_CHUNK_SIZE]; // protocol buffer for this connection
int buffer_length; // how many bytes received into this buffer
int pos; // how many bytes transmitted back out on fd_client from "buffer"
int has_data; // boolean to indicate protocol state (1 if there's still data in buffer to send)
};
如果无法一次发送所有内容,请在epoll模式下将fd_client套接字从EPOLLIN切换到EPOLLOUT。 在ConnectionState结构中将“ has_data”更改为true。 然后返回等待套接字事件。 当您能够再次发送时,请查看该套接字的ConnectionState结构,以确定是否仍然需要继续发送或接收新缓冲区。
注意边缘触发式插座。 当您从EPOLLOUT过渡回EPOLLIN时,您需要继续并再次recv()只是为了确保您不会丢失任何数据。 (类似地,要进入发送状态,请尝试初始发送)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.