1,關於Unix Socket
1.1 什麼是Socket?
Socket是網絡文件描述符。在基於Socket的編程技術中,用戶不直接訪問發送和接收包的網絡接口設備,而是建立一個中間文件描述符來處理編程接口到網絡的操作。
1.2 Socket包括哪些內容?
一個特殊的通信域,比如一個網絡連接
一個特殊的通信類型,比如流或者數據報
一個特殊的協議,比如TCP或者UDP
1.3 Unix的Socket() C函數詳細說明:
int socket(int domain, int type, int protocol)
domain的取值:
PF_UNIX Unix IPC通信
PF_INET IPV4通信
PF_INET6IPV6
PF_IPX Novell IPX
PF_NETLINKKernel用戶接口驅動程序
PF_X25 X.25
PF_AX25
PF_ATMPVCATM PVC
PF_APPLETALKAppleTalk協議
PF_PACKET低級包接口
type的取值:
SOCK_STREAM使用面向連接的通信包
SOCK_DGRAM使用無連接的通信包
SOCK_SEQPACKET使用有固定最大長度的面向連接的通信包
SOCK_RAW使用原IP包
SOCK_RDM使用不保證次序的可靠數據報
Protocol:
一般使用與type對應的默認協議,用0表示。
例如: int newsocket = socket(PF_INET, SOCK_STREAM, 0 );//使用TCP
1.4 使用面向連接的套接字
IP領域只有兩種類型: connection-oriented, connectionless
使用面向連接的套接字,服務器和客戶端需要如下通信方式:
Server Client
socket()socket()
bind()
listen()
accept() <----connect()
recv() <----send()
send() ---->recv()
close() <--->close()
1.5 使用無連接的套接字
SOCK_DGRAM使用UDP協議。通信方式如下:
UDP ServerUDP Client
socket()socket()
bind()
recvform() <---sendto()
sendto() --->recvform()
close() close()
1.6 使用無阻塞的I/O方法
什麼是阻塞?
比如使用recv(),如果函數接受不到數據,就會阻塞程序的繼續執行。
如何防止阻塞?
使用fcntl()函數,把套接字設置為無阻塞模式。
int newsocket;
newsocket = socket(PF_INET, SOCK_STREAM, 0 );
fcntl( newsocket, F_SETEL, O_NONBLOCK );
以後使用recv()就不會阻塞了。
另一種方式是使用多路套接字select()
2 WinSock技術
總的說來,就是模仿Unix socket的實現。
2.1 WinSock下的函數和流程
Server Client
WSAstartup()WSAStartup()
WSASocket()WASSocket()
bind()
listen()
WSAAccept() <--WSAConnect()
WSARecv() <--WSASend()
WSASend() -->WSARecv()
close() <->close()
WSACleanup()WSACleanup()
與Unix socket的最主要區別就是在最上面加了WSAStartup()函數,最後加了WSACleanup()函數。中間都是一樣的。
int WSAStartup(WORD wversion, LPWSADATA lpWSAData)
第一個參數是版本,要求2.2 還是1.1.
函數成功以後,lpWSAData指向一個結構體,包括win sock的一些信息。
WSACleanup()函數用來釋放winsocket庫,這個函數之後,再調用任何socket函數,都會出錯。
2.2 WinSock
2.2.1 采用類似Unix的方法
使用ioctlsocket()把socket設置為無堵塞的。
使用select()多路傳輸多個套接字。
2.2.2 使用WSAAsyncSelect()函數
WSAAsynSelect()擴展了Unix的select()函數,它允許Windows進行查詢套接字的操作。創建的WSAAsynSelect()方法包括要監視的套接字和一個Windows消息值,當某個套接字出現的時候,該消息就會送到窗口。
int WSAAsynSelect(Socket s, HWND hwnd, unsigned int wMsg, long lEvent)
Event包括如下事件類型:
FD_ACCEPT 用套接字建立一個新的連接
FD_ADDRESS_LIST_CHANGE為套接字的協議族而改變的本地地址列表
FD_CLOSE 一個現有的連接被關閉
FD_CONNECT 已經完成與遠程主機連接的套接字
FD_GROUP_QOS 套接字組的QOS已經改變
FD_OOB 套接字受到帶外的數據
FD_QOS 套接字的QOS已經改變
FD_READ 套接字有准備讀的數據
FD_ROUTING_INTERFACE_CHANGE套接字的路由接口已經改變到一個特殊的目的地
FD_WRITE 套接字准備寫數據
Example:
WSAAsynSelect( sock, hwnd, WM_SOCKET, FD_READ | FD_CLOSE );
2.2.3 使用WSAEventSelect()函數
為了適應一些應用程序例如精靈程序或者某些沒有用戶界面的服務程序(因此不使用窗口句柄),Windows Socket 2提供了WSAEventSelect()函數和WSAEnumNetworkEvents()函數。WSAEventSelect()函數和WSAAyncSelect()函數很類似,區別僅在於當一個FD_XXX網絡事件發生時,WSAEventSelect()函數將導致一個應用程序指定的事件對象被設置,而WSAAyncSelect()將導致一條Windows消息被發送(例如FD_READ,FD_WRITE等等)。