簡體   English   中英

C:使用epoll ET的數據轉發服務器填充發送緩沖區

[英]C: Data forwarding server using epoll ET fills the send buffer

我有以下情況。 我的服務器從遠程服務器(fd_server)接收數據,並將其轉發到客戶端(fd_client)。 我正在使用邊緣觸發的epoll,以便可以處理多個客戶端和多個服務器連接。

程序:

  1. 客戶端連接到服務器。
  2. 我的服務器連接到遠程服務器並請求數據。
  3. 遠程服務器響應,我的服務器將數據轉發到客戶端。

細節:

我的服務器連接到遠程服務器后,將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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM