簡體   English   中英

在C中接收時發送

[英]Sending while receiving in C

我在我的服務器上創建了一段代碼作為多線程

問題是,當我在另一個套接字上接收時,它不會發送數據。

因此,如果我向客戶端2發送一些內容到客戶端2,則client2僅在他自己發送內容時才會收到(跳出recv函數)..我該如何解決這個問題?

 /* Thread*/
while (! stop_received) {
        nr_bytes_recv = recv(s, buffer, BUFFSIZE, 0);

        if(strncmp(buffer, "SEND", 4) == 0) {
            char *message = "Text asads \n";
            rv = send(users[0].s, message, strlen(message), 0);
            rv = send(users[1].s, message, strlen(message), 0);
            if (rv < 0) {
                perror("Error sending");
                exit(EXIT_FAILURE);
            }           
        }else{
            char *message = "Unknown command \n";
            rv = send(s, message, strlen(message), 0);
            if (rv < 0) {
                perror("Error sending");
                exit(EXIT_FAILURE);
            }
        }
}

更具體一點,有幾種類型的I / O. 你目前所做的是阻塞i / o。 一般來說,這意味着當你調用sendrecv ,操作將“阻塞”直到它完成。

與此相反,存在所謂的非阻塞i / o。 在此i / o模型中,如果操作無法完成,則操作將立即返回。 通常, select函數與此i / o模型一起使用。

您可以在Select Tutorial中看到示例程序。 完整的源代碼位於頁面底部。

正如其他人所說,你的另一個選擇是使用線程。

您的代碼將阻止recv()調用。 編寫多線程應用程序,或研究select()函數的使用。

將發送和接收放在單獨的線程中。

我注意到你正在使用perror() (POSIX錯誤函數),這讓我相信你正在使用POSIX操作系統,這讓我懷疑它的GNU / Linux。

select()是可移植的, poll()是以POSIX為中心的, epoll()是以Linux為中心的。 如果使用GNU / Linux,我強烈建議避免使用select()並使用:

  • poll()如果您只輪詢幾十個文件描述符
  • epoll()如果你需要擴展到數千個連接,它可用。

如果您的應用程序不需要是可移植的,並且沒有要求禁止使用擴展,請使用poll()epoll() 一旦你了解了select()是如何工作的,你就會很樂意擺脫它,特別是對於必須擴展以服務於許多客戶的東西。

如果需要可移植性,請查看構建配置期間是否存在poll()epoll() ,並使用select()

注意, epoll()直到Linux 2.5(某事物)才出現,因此最好習慣使用它們。

你應該用兩個線程,一個發送器和一個接收器來分配代碼。

有點這樣:

 /* 1st Thread*/
while (! stop_received) {
        nr_bytes_recv = recv(s, buffer, BUFFSIZE, 0);
}


 /* 2nd Thread*/
while (! stop_received) {
        if(strncmp(buffer, "SEND", 4) == 0) {
            char *message = "Text asads \n";
            rv = send(users[0].s, message, strlen(message), 0);
            rv = send(users[1].s, message, strlen(message), 0);
            if (rv < 0) {
                perror("Error sending");
                exit(EXIT_FAILURE);
            }           
        }else{
            char *message = "Unknown command \n";
            rv = send(s, message, strlen(message), 0);
            if (rv < 0) {
                perror("Error sending");
                exit(EXIT_FAILURE);
            }
        }
}

並發性會帶來一些問題,比如訪問buffer變量。

有兩種方法可以實現您想要的目標:

1.)在不同的線程中實現發送和接收代碼。 但是會出現一些問題,比如不增加客戶端可能會讓你陷入麻煩來處理代碼。 還會有一些並發問題(如pcent所述)。 你可以去沒有阻塞插座,但我建議不要這樣做,因為我希望你不想要一個cpu豬。

2.)另一種方法是使用select()函數,它可以讓你同時監視不同類型的多個套接字。 有關“select()”的更多說明,您可以谷歌。 :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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