謝謝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