使用基本的socket函數
1.socket庫的2.2版本的文件:
dll文件:ws2_32.dll
lib文件:ws2_32.lib
頭文件:<WINSOCK2.H>
2.socket庫的初始化和卸載
2.1-初始化socket庫
int WSAStartup (
WORD wVersionRequested, //請求使用的庫的版本
LPWSADATA lpWSAData //返回可用的庫的信息
);
2.2-卸載socket庫
WSACleanup();
2.3-MFC提供了一個AfxSocketInit函數,該函數內部自動調用了WSAStartup函數和WSACleanup函數,利用該函數加載和卸載socket庫時,不需要為工程連接ws2_32.lib庫文件,僅需包含頭文件:#include <Afxsock.h>,且必須在應用的程序類的InitInstance函數中調用該函數,該函數加載的是1.1版本的socket庫;
BOOL AfxSocketInit( WSADATA* lpwsaData = NULL );
返回值:函數調用成功返回非0值,調用失敗返回0;
3.TCP通信
3.1-TCP服務器
1--創建服務器端socket
SOCKET socket (int af, int type, int protocol);
af:指定地址族,AF_UNIX/AF_LOCAL/AF_FILE--本地通信;AF_INET--網絡通信IPv4(主用);AF_INET6--網絡通信IPv6(前綴AF替換成PF效果一樣);
type:指定socket類型,SOCK_STREAM--流式套接字,SOCK_DGRAM--數據報式套接字;
protocol:推薦為0;
函數返回值:成功返回socket描述符;失敗返回一個INVALID_SOCKET值,錯誤信息可通過WSAGetLastError函數返回;
2--綁定IP地址和端口(bind)
int bind (SOCKET s, const struct sockaddr FAR* name, int namelen);
s:要綁定的套接字;
name:指定該套接字的通信地址信息,指向sockaddr結構體或sockaddr_un結構體或sockaddr_in結構體的指針變量;
nameLen:指定地址結構的長度;
函數返回值:成功返回0;失敗返回一個SOCKET_ERROR,錯誤信息可通過WSAGetLastError函數返回;
通信地址包括結構體:
struct sockaddr --主要用於做函數的參數,不負責存儲數據;
struct sockaddr {
unsigned short sa_family; //指定地址族
char sa_data[14]; //要求一塊內存分配區,起占位作用
};
struct sockaddr_in --負責存儲網絡通信的地址數據
struct sockaddr_in{
short sin_family; //指定地址族
unsigned short sin_port; //端口號
struct in_addr sin_addr; //主機IP地址
char sin_zero[8];
};
註:若本地機器具有多個網卡,則每個網卡均有自己的IP地址,可將IP地址指定為INADDR_ANY,允許向分配給本地機器的各個IP地址發送或接收數據;
3--監聽(listen)
int listen ( SOCKET s, int backlog );
s:套接字;
backlog:SOMAXCONN,設置等待隊列的最大長度(可接收的請求個數);
4--等待客戶端連接並接受(accept)
SOCKET accept ( SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen );
s:套接字;
addr:指向一個緩沖區,該緩沖區用來保存服務器端接受的發起連接的客戶端的IP地址信息和端口信息;
addrlen:返回包含地址信息的長度;
函數返回值:成功返回socket描述符;失敗返回一個INVALID_SOCKET值,錯誤信息可通過WSAGetLastError函數返回;
5--數據收發(send/recv)
int send ( SOCKET s, const char FAR * buf, int len, int flags );
s:套接字;
buf:指向一個緩沖區,該緩沖區包含將要傳遞的數據;
len:緩沖區的長度;
flags:設為0;
int recv ( SOCKET s, char FAR* buf, int len, int flags );
s:套接字;
buf:指向一個緩沖區,用來保存接收的數據;
len:緩沖區的長度;
flags:設為0;
6--關閉socket
int closesocket ( SOCKET s );
通過netstat -an,查看網絡端口狀態
3.2-TCP客戶端
1--創建客戶端socket
2--連接服務器,如果是本機 inet_addr("127.0.0.1");
int connect ( SOCKET s, const struct sockaddr FAR* name, int namelen );
s:套接字;
name:設定連接的服務器端地址信息;
namelen:指定服務器端地址的長度;
3--數據收發(send/recv)
4--關閉socket
4.UDP通信
4.1-UDP服務器
1--創建服務器端socket
2--綁定IP地址和端口(bind)
3--數據收發 recvfrom/sendto
int recvfrom ( SOCKET s, char FAR* buf, int len, int flags, struct sockaddr FAR* from, int FAR* fromlen );
s:套接字;
buf:指向一個緩沖區,用來接收數據;
len:緩沖區的長度;
flags:設為0;
from:指向地址結構體,用來接收發送數據方的地址信息;
fromlen:調用前須給一個初始值,函數調用後會返回地址結構的大小;
int sendto ( SOCKET s, const char FAR * buf, int len, int flags, const struct sockaddr FAR * to, int tolen );
s:套接字;
buf:指向一個緩沖區,包含將要發送的數據;
len:指定緩沖區中數據的長度;
flags:設為0;
to:可選指針,指定目標套接字的地址;
tolen:參數to指定的地址的長度;
4--關閉socket
4.2-UDP客戶端
1--創建客戶端socket
2--數據收發 sendto/recvfrom
3--關閉socket
5.IP地址格式和端口格式的轉換
5.1-IP地址格式的轉換
將點分十進制的IP地址轉為十六進制的格式:
unsigned long inet_addr ( const char FAR * cp );
將IP地址從十六進制轉為點分十進制的格式:
char FAR * inet_ntoa ( struct in_addr in );
5.2-端口格式的轉換
將本機端口的整數格式轉為TCP/IP網絡整數格式:
u_short htons ( u_short hostshort ); //16位
u_long htonl ( u_long hostlong ); //32位
將端口的網絡整數格式轉為本地端口的整數格式:
u_short ntohs ( u_short netshort );
5.3-主機名<-->IP地址
5.3.1主機名轉換為IP地址
函數gethostbyname從主機數據庫中獲取主機名相對應的IP地址;
struct hostent FAR * gethostbyname ( const char FAR * name );
name:指向一個主機名字符串;
返回值:函數返回hostent結構體類型的指針,該結構體類型的定義如下:
struct hostent {
char FAR * h_name;
char FAR * FAR * h_aliases;
short h_addrtype;
short h_length;
char FAR * FAR * h_addr_list;
};
該結構體的最後一個成員h_addr_list是一個指針數組,它的每個元素都是一個字符指針,指向內存中存放的一個個點分十進制表示的主機IP地址,一臺主機可能會有多個IP地址;
5.3.2IP地址轉換為主機名
函數gethostbyaddr將根據指定的IP地址獲取相應的主機信息;
struct HOSTENT FAR * gethostbyaddr (
const char FAR * addr,
int len,
int type
);
addr:是一個指向點分十進制類型的IP地址的指針;
len:地址長度;對於AF_INET地址族,長度必須為4個字節;
type:地址類型,Windows平臺下必須設為AF_INET;
返回值:函數也是返回hostent結構體類型的指針,結構體中的h_name數據成員就是主機名;
使用基本的socket函數