winsock WSAData SOCKET sockaddr_in sendto recvfrom
winsock
Winsock是Windows下的網路程式設計介面,它是由Unix下的BSD Socket發展而來,是一個與網路協議無關的程式設計介面。
構建程式設計環境
Winsock在常見的Windows平臺上有兩個主要的版本,即Winsock1和Winsock2。
- 使用WINSOCK.H標頭檔案時,同時需要庫檔案WSOCK32.LIB,
- 使用WINSOCK2.H時,則需要WS2_32.LIB,
- 如果使用MSWSOCK.H中的擴充套件API,則需要MSWSOCK.LIB。
正確引用了標頭檔案,並連結了對應的庫檔案,你就構建起編寫WINSOCK網路程式的環境了。
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")
初始化Winsock
每個Winsock程式必須使用WSAStartup載入合適的Winsock動態連結庫,如果載入失敗,WSAStartup將返回SOCKET_ERROR,這個錯誤就是WSANOTINITIALISED,WSAStartup的定義如下:
int WSAStartup(
WORD wVersionRequested,
LPWSADATA lpWSAData
);
wVersionRequested指定了你想載入的Winsock版本,其高位元組指定了次版本號,而低位元組指定了主版本號。 lpWSAData是一個指向WSAData結構的指標,WSAStartup會向該結構中填充其載入的Winsock動態鏈庫的資訊。
WSAData (Windows Sockets API)
這個結構被用來儲存 被WSAStartup函式呼叫後返回的 Windows Sockets資料。它包含Winsock.dll執行的資料。
typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
} WSADATA, FAR * LPWSADATA;
wVersion為你將使用的Winsock版本號,wHighVersion為載入的Winsock動態庫支援的最高版本,注意,它們的高位元組代表次版本,低位元組代表主版本。
szDescription與szSystemStatus由特定版本的Winsock設定,實際上沒有太大用處。
iMaxSockets表示最大數量的併發Sockets,其值依賴於可使用的硬體資源。
iMaxUdpDg表示資料報的最大長度;然而,獲取資料報的最大長度,你需要使用WSAEnumProtocols對協議進行查詢。最大數量的併發Sockets並不是什麼神奇的數字,它是由可用的物理資源來決定的.
lpVendorInfo是為Winsock實現而保留的製造商資訊,這個在Windows平臺上並沒有什麼用處.
套接字型別
SOCKET sockListener=socket(AF_INET, SOCK_DGRAM, 0);
int socket(int domain, int type, int protocol);
domain引數:
PF_INET, AF_INET: Ipv4網路協議;
PF_INET6, AF_INET6: Ipv6網路協議。
type:
SOCK_DGRAM: 如果你傳輸的是視訊音訊等資料,丟幾個包也無所謂的,可以採用UDP
SOCK_STREAM: 如果需要傳輸的資料是準確的,建議採用TCP,也就是SOCK_STREAM
引數protocol:
用來指定socket所使用的傳輸協議編號。這一引數通常不具體設定,一般設定為0即可。
sockaddr_in
用來處理網路通訊的地址。
sockaddr和sockaddr_in包含的資料都是一樣的,但他們在使用上有區別:
程式設計師不應操作sockaddr,sockaddr是給作業系統用的
一般的用法為:
程式設計師把型別、ip地址、埠填充sockaddr_in結構體,然後強制轉換成sockaddr,作為引數傳遞給系統呼叫函式
typedef struct sockaddr_in {
ADDRESS_FAMILY sin_family;
USHORT sin_port;
IN_ADDR sin_addr;
CHAR sin_zero[8];
} SOCKADDR_IN, *PSOCKADDR_IN;
Members
sin_family
The address family for the transport address. This member should always be set to AF_INET.
sin_port
A transport protocol port number.
sin_addr
An IN_ADDR structure that contains an IPv4 transport address.
sin_zero
Reserved for system use. A WSK application should set the contents of this array to zero.
Remarks
All of the data in the SOCKADDR_IN structure, except for the address family, must be specified in network-byte-order (big-endian).
bind()
int bind(int sockfd, struct sockaddr * my_addr, int addrlen);
函式說明:bind()用來設定給引數sockfd 的socket 一個名稱. 此名稱由引數my_addr 指向一sockaddr 結構,對於不同的socket domain 定義了一個通用的資料結構
sendto()
int sendto (int s, const void *buf, int len, unsigned int flags, const struct sockaddr *to, int tolen);
sendto(),是把UDP資料報發給指定地址;
recvfrom()
int recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);
recvfrom()是從指定地址接收UDP資料報
引數
- s: socket描述符。
- buf: UDP資料報快取地址。
- len: UDP資料報長度。
- flags: 該引數一般為0。
- to: sendto()函式引數,struct sockaddr_in型別,指明UDP資料發往哪裡報。
- tolen: 對方地址長度,一般為:sizeof(struct sockaddr_in)。
- fromlen:recvfrom()函式引數,struct sockaddr_in型別,指明從哪裡接收UDP資料報。
對於sendto()函式,成功則返回實際傳送出去的字元數,失敗返回-1,錯誤原因存於errno 中。