[英]bi-directional communication using socketpair: hangs reading output from child process
[英]Program structure for bi-directional TCP communication using Boost::Asio
首先,我希望我的問題有道理,甚至可能! 從我讀過的關於TCP套接字和Boost :: ASIO的內容來看,我認為應該如此。
我要做的是設置兩台機器,並在它們之間通過TCP實現雙向讀/寫鏈路。 任何一方都應該能夠發送一些數據供另一方使用。
關於TCP(/ IP?)的第一個令人困惑的部分是它需要這個客戶端/服務器模型。 然而,閱讀表明任何一方都能夠寫作或閱讀,所以我還沒有完全氣餒。 我不介意建立任意一方作為客戶端而另一方作為服務器。 在我的申請中,可以提前談判,而不是我擔心。
不幸的是,我遇到的所有示例似乎都集中在連接到服務器的客戶端上,並且服務器立即發回一些數據。 但我希望客戶端能夠寫入服務器。
我設想某種循環,其中我稱之為io_service.poll()
。 如果輪詢顯示另一方正在等待發送一些數據,它將調用read()
並接受該數據。 如果隊列中沒有任何等待,並且它有要發送的數據,那么它將調用write()
。 雙方都這樣做,他們應該能夠互相讀寫。
我關心的是如何避免兩者同時進入某些同步write()操作的情況。 他們都有數據發送,然后坐在那里等待雙方發送。 這個問題只是暗示我應該只進行異步write()
和read()
嗎? 在這種情況下,如果連接的兩端都試圖同時異步寫入,事情會爆發嗎?
我希望有人可以理想地:
1)提供一種非常高級的結構或最佳實踐方法,可以從客戶端和服務器的角度完成此任務
或者,理想情況下,
2)說我想做的事情是不可能的,也許建議某種形式的解決方法。
你想做的是絕對可能的。 Web流量是“客戶端”在服務器發送之前很久發送的情況的一個很好的例子。 我認為你被“客戶”和“服務器”這兩個詞搞砸了。
這些詞真正描述的是連接建立的方法。 在“客戶”的情況下,它是“活躍”的建立; 在“服務器”的情況下,它是“被動的”。 因此,您可能會發現使用“主動”和“被動”這兩個術語不那么令人困惑,或者至少以這種方式來考慮它們。
關於找到可以用作工作基礎的示例代碼,我強烈建議您查看W. Richard Stevens的“Unix網絡編程”一書。 任何版本都可以,但第2版將更新。 它只是C,但沒關系,因為套接字API只是C語言。 boost :: asio很不錯,但聽起來你可能會看到引擎蓋下的一些螺母和螺栓。
我關心的是如何避免兩者同時進入某些同步write()操作的情況。 他們都有數據發送,然后坐在那里等待雙方發送。 這個問題只是暗示我應該只進行異步write()和read()嗎? 在這種情況下,如果連接的兩端都試圖同時異步寫入,事情會爆發嗎?
聽起來你對如何使用協議感到有些困惑。 TCP僅提供可靠的字節流,僅此而已。 最重要的是,應用程序會說協議,因此他們知道何時以及要讀取和寫入多少數據。 如果雙方都沒有讀取數據,則客戶端和服務器同時寫入數據會導致死鎖。 解決該行為的一種方法是使用deadline_timer
取消異步寫入操作(如果它在一定時間內沒有完成)。
編寫服務器時應該使用異步方法。 同步方法適用於某些簡單的客戶端應用程序。
TCP是全雙工的,這意味着您可以按照所需的順序發送和接收數據。 為了防止您自己的協議中的死鎖(程序的高級行為),當您有機會發送和接收時,您應該優先接收。 在級別觸發模式下epoll看起來像:發送和接收epoll,如果你可以接收,否則如果你可以發送並有東西發送這樣做。 我不知道boost :: asio或thread如何適合這里; 你需要對發送和接收如何交錯進行一些控制。
您正在尋找的詞是“非阻塞”,這與POSIX異步I / O(涉及信號) 完全不同。
這個想法是你使用類似fcntl(fd,F_SETFL,O_NONBLOCK)
。 write()
將返回成功寫入的字節數(如果為正), read()
和write()
返回-1並設置errno = EAGAIN
如果“無法進行”(沒有數據讀取或寫入窗口已滿) 。
然后使用select / epoll / kqueue之類的東西阻塞,直到套接字可讀/可寫(取決於設置的標志)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.