兩個(gè)關(guān)鍵問題的解決方法
通常一臺(tái)服務(wù)器要連接多臺(tái)客戶機(jī),而每臺(tái)客戶機(jī)由于支持多用戶方式就會(huì)同時(shí)運(yùn)行多個(gè)c_process進(jìn)程。服務(wù)器如何準(zhǔn)確地將消息送給哪一臺(tái)客戶機(jī)? 另外一臺(tái)客戶機(jī)上運(yùn)行的每一個(gè)c_process進(jìn)程如何正確地獲取發(fā)送給自己的消息? 這是兩個(gè)關(guān)鍵的問題。 第一個(gè)問題在前面已經(jīng)講述過,主要是通過消息的sid標(biāo)志來區(qū)別的。第二個(gè)問題是這樣解決,在第①步時(shí)c_process進(jìn)程先將自身的進(jìn)程號(hào)pidc放在buf->cpid中,該值在以后的傳輸過程中保持不變,在第⑦步再將cpid賦值給消息類別mtype。這樣在第⑧時(shí)c_process進(jìn)程就從消息隊(duì)列qid2中取走消息類別mtype等于其自身進(jìn)程號(hào)pidc的消息,而不會(huì)錯(cuò)將送給同一客戶機(jī)別的c_process進(jìn)程的消息拿走。(圖3) ┌──────────────┐ ┌────────────┐
│Server ┌───┤ ├───┐ ┌─────┐│
│ │tcp_s │ ┌────┤tcp_c ├┐│c_process2││
│ ┌─────┐ └─┬─┤ │ ├───┤│└─────┘│
│ │s_process │┌───┴┐│ │ ┌─→┤tcp_c1││┌─────┐│
│ │服務(wù)程序 ││共享內(nèi)存││ │ │ L2├─┬─┘││c_process1││
│ └─┬─┬─┘└───┬┘│ │ │ │ ↓⑦ │└───┬┬┘│
│ ⑤↓ ↑④ ┌─┴─┤L1 │ │ │ │ └─┐ │↑⑧│
│┌──┘ │ ┌─┤tcp_s1├←──┘ │ │ │ ②↑ ││ │
││┌──┬┼┐③│ │ ├←┐L1’ │ │ │┌──┬┼┐①││ │
│││qid3│ ├←┘ ├───┤ │ │ │ ││qid1│ ├←┘│ │
││├──┼─┤ ┌┤tcp_s2├─┼───┘ │ │├──┼─┤ │ │
│││qid4│ ┼→─┘│ ├┐│┌────┐│ ││qid2│ ┼──┘ │
││└──┴┬┘⑥ └───┤│└┤ ││ │└──┴┬┘ │
│└────┘ │└→┤Client2 ││ └────┘ Client1 │
└──────────────┘ L2’└────┘└──────────┘
圖3 消息在服務(wù)器和客戶機(jī)內(nèi)傳送的過程
消息隊(duì)列與共享內(nèi)存
在運(yùn)行服務(wù)器通信軟件之前應(yīng)先創(chuàng)建共享內(nèi)存和消息隊(duì)列,創(chuàng)建共享內(nèi)存的方法見文獻(xiàn)[3]。本文共用到四個(gè)共享內(nèi)存操作函數(shù):shm_login(cport1,cport2,client_addr)在共享內(nèi)存中申請(qǐng)一條記錄將三個(gè)參數(shù)登記其中,并將flag標(biāo)志設(shè)為’i’表示已經(jīng)占用,同時(shí)根據(jù)記錄的位置賦值給記錄編號(hào)id。shm_logout(id)將共享內(nèi)存中第id條記錄刪除,并將后面的記錄前移,重新計(jì)算各條記錄的編號(hào)。shm_info(id,type)根據(jù)type查詢第id條記錄的內(nèi)容,比如type為GETS1時(shí)表示要查詢s_socket1的值,當(dāng)type等于GETLINKN時(shí)統(tǒng)計(jì)共享內(nèi)存的記錄總數(shù)。shm_update(id,s_socket1,s_socket2,linkf1,linkf2)修改第id條記錄的內(nèi)容,如果某個(gè)參數(shù)為零則不修改這個(gè)參數(shù),如shm_update(n,s2,0,1,0)只修改s_socket1和linkf1的值,其余內(nèi)容不作修改。在業(yè)務(wù)繁忙的情況下,有必要擴(kuò)大消息隊(duì)列的存儲(chǔ)容量,下面的例子將消息隊(duì)列qid3的容量擴(kuò)大兩倍。 來源:www.examda.com
struct msqid_ds sbuf1,*sbuf;int qid3;
sbuf=&sbuf1;
qid3=msgget(MSGKEY3,02000);
msgctl(qid1,IPC_STAT,sbuf);
sbuf->msg_qbytes*=2;
msgctl(qid3,IPC_SET,sbuf);
通常一臺(tái)服務(wù)器要連接多臺(tái)客戶機(jī),而每臺(tái)客戶機(jī)由于支持多用戶方式就會(huì)同時(shí)運(yùn)行多個(gè)c_process進(jìn)程。服務(wù)器如何準(zhǔn)確地將消息送給哪一臺(tái)客戶機(jī)? 另外一臺(tái)客戶機(jī)上運(yùn)行的每一個(gè)c_process進(jìn)程如何正確地獲取發(fā)送給自己的消息? 這是兩個(gè)關(guān)鍵的問題。 第一個(gè)問題在前面已經(jīng)講述過,主要是通過消息的sid標(biāo)志來區(qū)別的。第二個(gè)問題是這樣解決,在第①步時(shí)c_process進(jìn)程先將自身的進(jìn)程號(hào)pidc放在buf->cpid中,該值在以后的傳輸過程中保持不變,在第⑦步再將cpid賦值給消息類別mtype。這樣在第⑧時(shí)c_process進(jìn)程就從消息隊(duì)列qid2中取走消息類別mtype等于其自身進(jìn)程號(hào)pidc的消息,而不會(huì)錯(cuò)將送給同一客戶機(jī)別的c_process進(jìn)程的消息拿走。(圖3) ┌──────────────┐ ┌────────────┐
│Server ┌───┤ ├───┐ ┌─────┐│
│ │tcp_s │ ┌────┤tcp_c ├┐│c_process2││
│ ┌─────┐ └─┬─┤ │ ├───┤│└─────┘│
│ │s_process │┌───┴┐│ │ ┌─→┤tcp_c1││┌─────┐│
│ │服務(wù)程序 ││共享內(nèi)存││ │ │ L2├─┬─┘││c_process1││
│ └─┬─┬─┘└───┬┘│ │ │ │ ↓⑦ │└───┬┬┘│
│ ⑤↓ ↑④ ┌─┴─┤L1 │ │ │ │ └─┐ │↑⑧│
│┌──┘ │ ┌─┤tcp_s1├←──┘ │ │ │ ②↑ ││ │
││┌──┬┼┐③│ │ ├←┐L1’ │ │ │┌──┬┼┐①││ │
│││qid3│ ├←┘ ├───┤ │ │ │ ││qid1│ ├←┘│ │
││├──┼─┤ ┌┤tcp_s2├─┼───┘ │ │├──┼─┤ │ │
│││qid4│ ┼→─┘│ ├┐│┌────┐│ ││qid2│ ┼──┘ │
││└──┴┬┘⑥ └───┤│└┤ ││ │└──┴┬┘ │
│└────┘ │└→┤Client2 ││ └────┘ Client1 │
└──────────────┘ L2’└────┘└──────────┘
圖3 消息在服務(wù)器和客戶機(jī)內(nèi)傳送的過程
消息隊(duì)列與共享內(nèi)存
在運(yùn)行服務(wù)器通信軟件之前應(yīng)先創(chuàng)建共享內(nèi)存和消息隊(duì)列,創(chuàng)建共享內(nèi)存的方法見文獻(xiàn)[3]。本文共用到四個(gè)共享內(nèi)存操作函數(shù):shm_login(cport1,cport2,client_addr)在共享內(nèi)存中申請(qǐng)一條記錄將三個(gè)參數(shù)登記其中,并將flag標(biāo)志設(shè)為’i’表示已經(jīng)占用,同時(shí)根據(jù)記錄的位置賦值給記錄編號(hào)id。shm_logout(id)將共享內(nèi)存中第id條記錄刪除,并將后面的記錄前移,重新計(jì)算各條記錄的編號(hào)。shm_info(id,type)根據(jù)type查詢第id條記錄的內(nèi)容,比如type為GETS1時(shí)表示要查詢s_socket1的值,當(dāng)type等于GETLINKN時(shí)統(tǒng)計(jì)共享內(nèi)存的記錄總數(shù)。shm_update(id,s_socket1,s_socket2,linkf1,linkf2)修改第id條記錄的內(nèi)容,如果某個(gè)參數(shù)為零則不修改這個(gè)參數(shù),如shm_update(n,s2,0,1,0)只修改s_socket1和linkf1的值,其余內(nèi)容不作修改。在業(yè)務(wù)繁忙的情況下,有必要擴(kuò)大消息隊(duì)列的存儲(chǔ)容量,下面的例子將消息隊(duì)列qid3的容量擴(kuò)大兩倍。 來源:www.examda.com
struct msqid_ds sbuf1,*sbuf;int qid3;
sbuf=&sbuf1;
qid3=msgget(MSGKEY3,02000);
msgctl(qid1,IPC_STAT,sbuf);
sbuf->msg_qbytes*=2;
msgctl(qid3,IPC_SET,sbuf);