求sock连接池相关思路。300分!(100分)

A

AIHUA

Unregistered / Unconfirmed
GUEST, unregistred user!
公司要求做一个项目 其中用到sock连接池。
我对连接池的概念略知一二。可是书上只是说概念,没有给出涉及思路
本人才疏学浅,知道凭一人之力,是搞不明白啦~~ ;)
讨论一下 好吗?
 
顶顶。学习。
 
你可以看看这个 相信会对你有所帮助
http://www.cwdn.net/article/java/tip1.htm
 
好 我去看看
 
看看这个好了!

Winsock程式設計





l WSAStartup():連結應用程式與 Windows Sockets DLL 的第一個函式。

格 式: int PASCAL FAR WSAStartup( WORD wVersionRequested,
LPWSADATA lpWSAData );

參 數: wVersionRequested 可使用的 Windows Sockets API 最高版本
lpWSAData 指向 WSADATA 資料的指標

struct WSAData {
WORD wVersion; /* 版本,用1.1,(WORD)((1<<8)|1} */
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYSSTATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
};

傳回值: 成功 - 0
失敗 - WSASYSNOTREADY / WSAVERNOTSUPPORTED / WSAEINVAL

說明: 此函式「必須」是應用程式呼叫到 Windows Sockets DLL 函式中
的第一個,也唯有此函式呼叫成功後,才可以再呼叫其他 Windows Sockets DLL 的函式。此函式亦讓使用者可以指定要使用的 Windows Sockets API 版本,及獲取設計者的一些資訊。 (* 目前只提供 WINSOCK 第 1.1 版的功能)

範例:
if (WSAStartup((WORD)((1<<8)|1}, (LPWSDATA)&WSADATA)!=0){
MessageBox(NULL, “WSAStartup fail”,””,MB_OK);
return 0L;
}

l socket():建立Socket。

格 式: SOCKET PASCAL FAR socket( int af,
int type,
int protocol );

參 數: af 目前只提供 PF_INET(AF_INET)
type Socket 的型態 (SOCK_STREAM、SOCK_DGRAM)
protocol 通訊協定(如果使用者不指定則設為0)

傳回值: 成功 - Socket 的識別碼
失敗 - INVALID_SOCKET(呼叫 WSAGetLastError() 可得知原因)

說明: 此函式用來建立一 Socket,並為此 Socket 建立其所使用的資源。
Socket 的型態可為 Stream Socket 或 Datagram Socket。

範例:
tcp_sock = socket(PF_INET, SOCK_STREAM, 0);
udp_sock = socket(PF_INET, SOCK_DGRAM, 0);

l bind():指定 Socket 的 Local 位址 (Address)。

格 式: int PASCAL FAR bind( SOCKET s,
const struct sockaddr FAR *name,
int namelen );

參 數: s Socket的識別碼
name Socket的位址值,其格式為
struct sockaddr {
u_short sa_family;
char sa_data[14];
};
namelen name的長度

傳回值: 成功 - 0
失敗 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)

說明: 此一函式是指定 Local 位址及 Port 給某一未定名之 Socket。
使用者若不在意位址或 Port 的值,那麼他可以設定位址為 INADDR_ANY,及 Port 為 0;那麼Windows Sockets 會自動將其設定適當之位址及 Port (1024 到 5000之間的值),使用者可以在此 Socket 真正連接完成後,呼叫 getsockname() 來獲知其被設定的值。
範例:
struct sockaddr_in sa;
sa.sin_family = PF_INET;
sa.sin_port = htons(5001); /* host to network for short int */
sa.sin_addr.s_addr = INADDR_ANY;
bind(sock, (struct sockaddr far *)&sa, sizeof(sa));

l listen():設定 Socket 為監聽狀態,準備被連接。
格 式: int PASCAL FAR listen( SOCKET s, int backlog );
參 數: s Socket 的識別碼
backlog 未真正完成連接前(尚未呼叫 accept 前)彼端的連接要 求的最大個數
傳回值: 成功 - 0
失敗 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
說明: 使用者可利用此函式來設定 Socket 進入監聽狀態,並設定最多可有多少個在未真正完成連接前的彼端的連接要求。(目前最大值限制為 5, 最小值為1)
範例: listen(sock, 1)

呼叫完 listen 後,此時 Client 端如果來連接的話,Client 端的連接動作(connect)會成功,不過此時 Server 端必須再呼叫 accept() 函式,才算正式完成 Server 端的連接動作。

l accept():接受某一 Socket 的連接要求,以完成 Stream Socket 的連接。
格 式: SOCKET PASCAL FAR accept( SCOKET s, struct sockaddr FAR *addr, int FAR *addrlen );
參 數: s Socket的識別碼
addr 存放來連接的彼端的位址
addrlen addr的長度
傳回值:成功 - 新的Socket識別碼
失敗 - INVALID_SOCKET (呼叫 WSAGetLastError() 可得知原因)
說明: Server 端之應用程式呼叫此一函式來接受 Client 端要求之 Socket 連接動作;如果Server 端之 Socket 是為 Blocking 模式,且沒有人要求連接動作,那麼此一函式會被 Block 住;如果為 Non-Blocking 模式,此函式會馬上回覆錯誤。accept() 函式的答覆值為一新的 Socket,此新建的 Socket 不可再用來接受其它的連接要求;但是原先監聽之 Socket 仍可接受其他人的連接要求。

TCP socket 的 Server 端在呼叫 accept() 後,會傳回一個新的 socket 號碼;而這個新的 socket 號碼才是真正與 Client 端相通的 socket。比如說,我們用 socket() 建立了一個 TCP socket,而此 socket 的號碼(系統給的)為 1,然後我們呼叫的 bind()、listen()、accept() 都是針對此一 socket;當我們在呼叫 accept() 後,傳回值是另一個 socket 號碼(也是系統給的),比如說 3;那麼真正與 Client 端連接的是號碼 3 這個 socket,我們收送資料也都是要利用 socket 3,而不是 socket 1。

範例:

struct sockaddr_in sa;
int sa_len = sizeof(sa);
new_sock = accept(sock, (struct sockaddr far *)&sa, &sa_len)

至此,server端已ready for communication. 使用TCP者可用send/recv傳收資料,使用UDP者則用sendto/recvfrom。

l send():使用連接式的 Socket 傳送資料。
格 式: int PASCAL FAR send( SOCKET s,
const char FAR *buf,
int len,
int flags );
參 數: s Socket 的識別碼
buf 存放要傳送的資料的暫存區
len buf 的長度
flags 此函式被呼叫的方式
傳回值: 成功 - 送出的資料長度
失敗 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
說明: 此函式適用於連接式的 Datagram 或 Stream Socket 來傳送資料。
對 Datagram Socket 言,若是 datagram 的大小超過限制,則將不會送出
任何資料,並會傳回錯誤值。若是傳送 (transport) 系統內之儲存空間不
夠存放這些要傳送的資料,send() 將會被 block 住,除非該 Socket 被設
定為 non-blocking 模式。使用者亦須注意 send()函式執行完成,並不表
示資料已經成功地送抵對方了。 flags 的值可設為 MSG_DONTROUTE
(*暫不提供此功能)及 MSG_OOB 的組合。

l recv():自 Socket 接收資料。

格 式: int PASCAL FAR recv( SOCKET s,
char FAR *buf,
int len,
int flags );

參 數: s Socket 的識別碼
buf 存放接收到的資料的暫存區
len buf 的長度
flags 此函式被呼叫的方式

傳回值: 成功 - 接收到的資料長度 (若對方 Socket 已關閉,則為 0)
失敗 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)

說明: 此函式用來自連接式的 Datagram Socket 或 Stream Socket 接收資料。對 Stream Socket 言,我們可以接收到目前有效的 (available) 資料,但其數量不超過 len 的大小。若是此 Socket 設定 SO_OOBINLINE,且有 out-of-band 的資料未被讀取,那麼只有 out-of-band 的資料被取出。對 Datagram Socket 言,只取出第一個 datagram;若是該 datagram 大於使用者提供的儲存空間,那麼只有該空間大小的資料被取出,多餘的資料將遺失,且回覆錯誤的訊息。 flags 的值可為 MSG_PEEK、MSG_OOB (*暫不提供此功能)的組合。

l sendto():將資料送到指定的目的地。
格 式: int PASCAL FAR sendto( SOCKET s,
const char FAR *buf,
int len,
int flags,
const struct sockaddr FAR *to,
int tolen );

參 數: s Socket 的識別碼
buf 存放要傳送的資料的暫存區
len buf 的長度
flags 此函式被呼叫的方式
to 資料要送達的位址
tolen to 的大小

傳回值: 成功 - 送出的資料長度
失敗 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)

說明: 此函式適用於 Datagram 或 Stream Socket 來傳送資料到指定的位址。
對 Datagram Socket 言,若是 datagram 的大小超過限制,則將不會送出任何資料,並會傳回錯誤值。對 Stream Socket 言,其作用與 send() 相同;參數 to 及 tolen 在此並無作用。 若是傳送 (transport) 系統內之儲存空間不夠存放這些要傳送的資料,sendto() 將會被 block 住,除非該 Socket 被設定為 non-blocking 模式。使用者亦須注意 sendto() 函式執行完成,並不表示資料已經成功地送抵對方了。 flags 的值可設為 MSG_DONTROUTE(*暫不提供此功能)及 MSG_OOB 的組合。

l recvfrom():讀取一個 Datagram,並儲存資料來源的位址。

格 式: int PASCAL FAR recvfrom( SOCKET s,
char FAR *buf,
int len,
int flags,
struct socketaddr FAR *from,
int FAR *fromlen );

參 數: s Socket 的識別碼
buf 存放接收到的資料的暫存區
len buf 的長度
flags 此函式被呼叫的方式
from 資料來源的位址
fromlen from 的大小

傳回值: 成功 - 接收到的資料長度 (若對方 Socket 已關閉,則為 0)
失敗 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)

說明: 此函式用來讀取資料並記錄資料來源的位址。對 Stream Socket 言,其作用與 recv() 相同,參數 from 及 fromlen 將不被用到。

l closesocket():關閉某一Socket。
格 式: int PASCAL FAR closesocket( SOCKET s );
參 數: s Socket 的識別碼
傳回值:成功 - 0
失敗 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
說明: 此一函式是用來關閉某一 Socket。
若是使用者原先對要關閉之 Socket 設定 SO_DONTLINGER,則在呼叫此一函式後,會馬上回覆,但是此一 Sokcet 尚未傳送完畢的資料會繼續送完後才關閉。
若是使用者原先設定此 Socket 為 SO_LINGER,則有兩種情況:
(a) Timeout 設為 0 的話,此一 Socket 馬上重新設定 (reset),未傳完或未收到的資料全部遺失。
(b) Timeout 不為 0 的話,則會將資料送完,或是等到 Timeout 發生後才真正關閉。

程式結束前,讀者們可千萬別忘了要呼叫 WSACleanup() 來通知 Winsock Stack;如果您不呼叫此一函式,Winsock Stack 中有些資源可能仍會被您佔用而無法清除釋放喲。

l WSACleanup():結束 Windows Sockets DLL 的使用。
格 式: int PASCAL FAR WSACleanup( void );
參 數: 無
傳回值: 成功 - 0
失敗 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
說明: 應用程式在使用 Windows Sockets DLL 時必須先呼叫 WSAStartup() 來向 Windows Sockets DLL 註冊;當應用程式不再需要使用 Windows Sockets DLL 時,須呼叫此一函式來註銷使用,以便釋放其占用的資源。

l Client端之程式:
connect():要求連接某一 TCP Socket 到指定的對方。
格 式: int PASCAL FAR connect( SOCKET s, const struct sockaddr
FAR *name, int namelen );
參 數: s Socket 的識別碼
name 此 Socket 想要連接的對方位址
namelen name的長度
傳回值: 成功 - 0
失敗 - SOCKET_ERROR (呼叫WSAGetLastError()可得知原因)
說明: 此函式用來向對方要求建立連接。若是指定的對方位址為 0 的話,會傳回錯誤值。當連接建立完成後,使用者即可利用此一 Socket 來做傳送或接收資料之用了。
範例:
struct sockaddr_in sa;
sa.sin_family = PF_INET;
sa.sin_port = htons(5001); /* server’s port number*/
sa.sin_addr.s_addr = htonl(serverip);
connect(sock, (struct sockaddr far *)&sa, sizeof(sa));

Asynchronous Control

設定aasynchronous mode, 等event發生時,系統通知後再處理。
l WSAAsyncSelect():要求某一 Socket 有事件 (event) 發生時通知使用者。
格 式: int PASCAL FAR WSAAsyncSelect( SOCKET s, HWND hWnd,
unsigned int wMsg, long lEvent );
參 數: s Socket 的編號
hWnd 動作完成後,接受訊息的視窗 handle
wMsg 傳回視窗的訊息
lEvent 應用程式有興趣的網路事件
傳回值: 成功 - 0
失敗 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
說明: 此函式是讓使用者用來要求 Windows Sockets DLL 在偵測到某一 Socket 有網路事件時送訊息到使用者指定的視窗;網路事件是由參數 lEvent 設定。呼叫此函式會主動將該 Socket 設定為 Non-blocking 模式。lEvent 的值可為以下之「OR」組合:(參見 WINSOCK第1.1版88、89頁) FD_READ、FD_WRITE、FD_OOB、FD_ACCEPT、FD_CONNECT、FD_CLOSE 使用者若是針對某一Socket再次呼叫此函式時,會取消對該 Socket 原先之設定。若要取消對該Socket 的所有設定,則 lEvent 的值必須設為 0。



範例:
在 Winmain() 中
hwnd = CreateWindow(…);
要系統在sock這個socket完成accept()後,通知hwnd這個window, 則
WSAAsyncSelect(sock,hwnd,ASYNC_EVENT,FD_ACCEPT);
Note: 可以call WSAAsyncSelect一次以上。
要取消這個asynchronous mode設定,則
WSAAsyncSelect(sock,hwnd,0,0);
l Catch Message
在WndProc() 中
switch (message) {
case ASYN_EVENT: {
….. process ….
}
}
其中
wParam存那一socket發生event
lParam的HIWORD存error code
lParam的LOWORD存event code

範例:
switch (WSAGETSELECTEVENT(lParam)) {
case FD_ACCEPT: {
if (WSAGETSELECTERROR(lParam)!=0) {
showmsg(“error at asynchronous accept!”);
}
…….
……
}
case FD_READ: {
……
……
}
}

如果有一個以上的socket在等asynchronous event,則可用wParam辨別,如
send(wParam,&buf, strlen(buf),0);
recv(wParam,&buf,sizeof(buf));
FD_WRITE event發生時機: socket可以傳且system buffer有空。
buffer overflow code為10035 (WSAEWOULDBLOCK)
l Blocking
有些動作(如read)會造成blocking,此時若有其他event發生,可以利用WSAIsBlocking()檢查是否有block,若有再用WSACancelBlockingCall()取消blocking之動作。
在Windows 3.1下,若是blocked時,會做下列事
for (;;) {
while (Blocking Hook());
if (operation_cancel());
if (operation_complete());
break;
}

Block Hook() {
MSG msg;
BOOL ret;
ret = (BOOL) PeekMessage(&msg,NULL,0,0,PM_REMOVE);
if (ret) {
TranslateMessage(&msg);
Dispatch Message(&meg);
}
return ret;
}

l ioctlsocket():控制 Socket 的模式。
格 式: int PASCAL FAR ioctlsocket( SOCKET s, long cmd, u_long FAR *argP );
參 數: s Socket 的識別碼
cmd 指令名稱
argP 指向 cmd 參數的指標
傳回值:成功 - 0
失敗 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
說明: 此函式用來獲取或設定 Socket 的運作參數。其所提供的指令有:(參見 WINSOCK 第 1.1 版 35、36 頁)
cmd 的值可為:
FIONBIO -- 開關 non-blocking 模式
FIONREAD -- 自 Socket 一次可讀取的資料量(目前 in buffer 的資料量)
SIOCATMARK -- OOB 資料是否已被讀取完
範例:
ioctlsocket(sock, FIONREAD, (u_long FAR)&argP);
l select():檢查一或多個 Sockets 是否處於可讀、可寫或錯誤的狀態。

格 式: int PASCAL FAR select( int nfds,
fd_set FAR *readfds,
fd_set FAR *writefds,
fd_set FAR *exceptfds,
const struct timeval FAR *timeout );

參 數: nfds 此參數在此並無作用
readfds 要被檢查是否可讀的 Sockets
writefds 要被檢查是否可寫的 Sockets
exceptfds 要被檢查是否有錯誤的 Sockets (*暫無作用)
timeout 此函式該等待的時間。若為 NULL 時,
表示 blocking,此函式會等到有事件發生。

傳回值: 成功 - 符合條件的 Sockets 總數 (若 Timeout 發生,則為 0)
失敗 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)

說明: 使用者可利用此函式來檢查 Sockets 是否有資料可被讀取,
或是有空間可以寫入,或是有錯誤發生。

範例:
FD_ZERO(*set); /* reset a set */
FD_SET(s, *set); /* add s into set */
FD_CLR(s, *set); /* delete s from set*/
FD_ISSET(s, *set); /* Is s in the set */

timeout.tv_sec = 0;
timeout.tv_usec = 100000;

select(nfds, readset, writeset, exceptset, &timeout);


 
多人接受答案了。
 
顶部