看板 C_and_CPP 關於我們 聯絡資訊
謝謝p大的講解 有幾個問題再提出來請教 1. 針對p大說的 我自己有測試 用你提供的sample code ========================================================================= 建立 named pipe (具名管線) 是用 CreateNamedPipe() 函數,在伺服端第一次指名 要建管線名稱 "purpose" 時,會返回第一個 "instance" 的參考,假設是 hPipe。 此時繼續使用 HANDLE hPipe2 = CreateNamedPipe(..) 可得到第二個 "instance"。 然後你 ConnectNamedPipe(hPipe, NULL) 完再 ConnectNamedPipe(hPipe2, NULL) 就同時連接兩個客戶端了,沒有第二個讀不到。 ========================================================================= 想問一下 我會遇到ERROR_PIPE_BUSY 我在想是不是該設定 __in DWORD nMaxInstances, 為多個 讓client可以取得多個kernel object? 想確認, 多個client雖然取得同一個pipe handle 是否他們的in / out buffer都是各自獨立? 我自己測試 當client1 讀完server資料後 client2 就卡在readfile 直到server關掉後才return fail, error = ERROR_BROKEN_PIPE 也同時看了下面的範例... 好像要這樣寫 持續去等待client來連 http://msdn.microsoft.com/en-us/library/windows/desktop/aa365588(v=vs.85).aspx 他似乎是一個loop 接到一個case就開一條thread去serve... 但是這樣很怪 若同一個時間點 兩個client同時去連接server 我的感覺是只有一個client搶的到handle 另一個會got error 當createFile...但我這還沒驗證 若假設成立 是不是client要有retry機制 當得到error 隔一段interval再去嘗試連接?? 不曉得這結論是否正確 2. 以這樣看named pipe 是不是無法做到 client間互相可以交流資訊(local namedpipe來說) 因為每個client 和 server建立連線後 in/out buffer似乎是各自獨立 只能和server互動@@ 3. http://tinyurl.com/a46eacj server code // This call blocks until a client process reads all the data const wchar_t *data = L"*** Hello Pipe World ***"; DWORD numBytesWritten = 0; result = WriteFile( 會卡在writefile 但看p大的sample 似乎是卡在FlushFileBuffers 請問這兩段server code 是不是有甚麼差異導致行為有不同呢? 謝謝˙ ※ 引述《purpose (purpose)》之銘言: : : 推 QQ29:看named pipe 假設同時有兩個client readfile... 01/26 00:43 : → QQ29:他會讓第一個讀完 看註解server就exit了 然後第二個就讀不到 01/26 00:44 : → QQ29:覺得很怪...還是說server要while一直重創pipe... 01/26 00:44 : → QQ29:我自己試試看 感覺好像是一次性的 同時讀"好像"一個拿不到 01/26 00:50 : 建立 named pipe (具名管線) 是用 CreateNamedPipe() 函數,在伺服端第一次指名 : 要建管線名稱 "purpose" 時,會返回第一個 "instance" 的參考,假設是 hPipe。 : 此時繼續使用 HANDLE hPipe2 = CreateNamedPipe(..) 可得到第二個 "instance"。 : 然後你 ConnectNamedPipe(hPipe, NULL) 完再 ConnectNamedPipe(hPipe2, NULL) : 就同時連接兩個客戶端了,沒有第二個讀不到。 : → QQ29:自己可能還要試試看 若client連上後去write pipe會不會蓋掉 01/26 01:01 : → QQ29:server原本寫的...然後就deadlock? 沒人讀(若只有一條thread) 01/26 01:02 : 甲端把資料輸出到 named pipe: : 對於乙端來說,等於是自己的 Input 區被填入, : 若同時間乙端把資料也輸出到同一個 named pipe,則是寫入到自己的 Output 區。 : 根本就不同位置。 : 推 QQ29:測試發現server writefile若client有讀過, server第二次 01/26 01:13 : → QQ29:write就完全不會block 滿奇怪的..感覺pipe真的只能用一次.. 01/26 01:13 : 能用很多次,這是緩衝區不夠大,只要空間夠,可以連續做 WriteFile 的動作, : 不管對方有沒有讀過。 : 下面我提供一份範例,流程是這樣: : 1. 伺服端啟動,並且開始監聽連線 : 2. 客戶端啟動,雙方以 named pipe 連線成功 : 3. 雙方同時進行寫入資料的動作,其中客戶端會連續做三次 write pipe : 4. 伺服端睡眠 8 秒,然後才對 named pipe 做唯一一次的讀取 : 伺服端執行畫面 : server is listening... : numBytes for writefile = 8 : sleeping... : numBytes for writefile = 8 : numBytes for readfile = 68 : AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBC : 客戶端執行畫面 : numBytes for writefile = 32 : numBytes for writefile = 32 : numBytes for writefile = 4 : all done, stop... : ######## : 線上程式碼:http://ideone.com/z2pRRF : /* filename: pipe_server.c */ : #define UNICODE : #include <windows.h> : #include <stdio.h> : int main() { : wchar_t buf[1024]; : int numBytes = 0; : BOOL writeGood = FALSE; : HANDLE hPipe = NULL; : hPipe = CreateNamedPipe(L"\\\\.\\pipe\\purpose", : PIPE_ACCESS_DUPLEX, : PIPE_TYPE_BYTE, : 1, : 512, /* out-buf size */ : 512, /* in-buf size */ : 0, : NULL); : if (hPipe == INVALID_HANDLE_VALUE) { : _putws(L"hPipe error.\n"); : return 0; : } : puts("server is listening..."); : if (ConnectNamedPipe(hPipe, NULL) == TRUE) { : writeGood = WriteFile(hPipe, L"^_^", 8, &numBytes, NULL); : printf("numBytes for writefile = %d\n", numBytes); : if (writeGood == FALSE) return 0; : _putws(L"sleeping..."); : Sleep(8000); : writeGood = WriteFile(hPipe, L">_<", 8, &numBytes, NULL); : printf("numBytes for writefile = %d\n", numBytes); : if (writeGood == FALSE) return 0; : ReadFile(hPipe, : buf, : 1024 * sizeof(wchar_t), : &numBytes, : NULL); : printf("numBytes for readfile = %d\n", numBytes); : _putws(buf); : } : FlushFileBuffers(hPipe); : DisconnectNamedPipe(hPipe); : CloseHandle(hPipe); : return 0; : } : ######## : ==================== : 線上程式碼:http://ideone.com/FRZgJr : /* filename: pclient.c */ : #define UNICODE : #include <windows.h> : #include <stdio.h> : int main() { : wchar_t buf[1024]; : int numBytes = 0; : BOOL writeGood = FALSE; : HANDLE hPipe = NULL; : hPipe = CreateFile(L"\\\\.\\pipe\\purpose", : GENERIC_READ | GENERIC_WRITE, : 0, : NULL, : OPEN_EXISTING, : 0, : NULL); : if (hPipe == INVALID_HANDLE_VALUE) { : _putws(L"hPipe error.\n"); : return 0; : } : writeGood = WriteFile(hPipe, L"AAAAAAAAAAAAAAAA", 32, &numBytes, NULL); : printf("numBytes for writefile = %d\n", numBytes); : if (writeGood == FALSE) return 0; : Sleep(500); : writeGood = WriteFile(hPipe, L"BBBBBBBBBBBBBBBB", 32, &numBytes, NULL); : printf("numBytes for writefile = %d\n", numBytes); : if (writeGood == FALSE) return 0; : Sleep(500); : writeGood = WriteFile(hPipe, L"C", 4, &numBytes, NULL); : printf("numBytes for writefile = %d\n", numBytes); : _putws(L"all done, stop..."); : system("pause"); : CloseHandle(hPipe); : return 0; : } : ==================== : 把原始碼中的 512, /* in-buf size */ 改成比如 12 (bytes) : 則客戶端第二次 write pipe 就會失敗,重現最上面推文提到的問題。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 123.192.100.51