qt socket 传递结构体 结构体中有list_计算机网络应用--Socket编程实验(二)
生活随笔
收集整理的這篇文章主要介紹了
qt socket 传递结构体 结构体中有list_计算机网络应用--Socket编程实验(二)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本節關于socket部分函數庫列表,具體基于socket的實例實現代碼見下節。給出基于winSocket的簡單websever實例。
2.1 WSAStartup()
【函數原型】
int WSAStartup (WORD wVersionRequested, LPWSADATA lpWSAData );【參數】
wVersionRequested[in] 表示欲使用的Windows Sockets API版本;這是個WORD類型的整數,高字節定義的是次版本號,低字節定義的是主版本號。lpWSAData
[in] 指向WSAData資料的指針。WSAData是結構數據類型,描述了關于Windows Sockecs底層實現的相關信息。
【返回值】
函數執行成功返回0,失敗則返回如下錯誤代碼:WSASYSNOTREADY: 底層網絡子系統沒有準備好。WSAVERNOTSUPPORTED:Winsock版本信息號不支持。WSAEINPROGRESS: 阻塞式Winsock1.1存在于進程中。WSAEPROCLIM: 已經達到Winsock使用量的上限。WSAEFAULT: lpWSAData不是一個有效的指針。【函數功能】
這個函數是應用程序應該第一個調用的Winsock API函數,以完成一系列初始化的工作。【相關數據結構】
WSADATA的定義如下: typedef struct WSAData { WORD wVersion; WORD wHighVersion; char szDescription[WSADESCRIPTION_LEN+1]; char szSystemStatus[WSASYS_STATUS_LEN+1]; unsigned short iMaxSockets; unsigned short iMaxUdpDg; char FAR * lpVendorInfo; } WSADATA, FAR * LPWSADATA;其中,各結構成員的含義為:
wVersion應用程序應該使用的Winsock版本號。wHighVersion
DLL所支持的最高版本號。通常應該等于wVersion。szDescription
以0結尾的ASCII字符串,關于Winsock底層實現的描述信息。szSystemStatus
以0結尾的ASCII字符串,關于Winsock底層狀態或者配置信息。iMaxSockets
一個進程最多可使用的套接字數,僅用于Winsock1.1,Winsock 2.0應該忽略該成員。iMaxUdpDg
最大的UDP報文大小,僅用于Winsock1.1,Winsock 2.0應該忽略該成員。對于Winsock 2.0,應該使用getsockopt函數取得SO_MAX_MSG_SIZE。lpVendorInfo
Winsock開發廠商信息,,僅用于Winsock1.1,Winsock 2.0應該忽略該成員。對于Winsock 2.0,應該使用getsockopt函數取得PVD_CONFIG。
【示例代碼】
#include <winsock.h> //對于Winsock 2, include <winsock2.h>WSADATA wsaData; int nRc = WSAStartup(0x0101, & wsaData); if(nRc) { //Winsock初始化錯誤 return; } if(wsaData.wVersion != 0x0101) { //版本支持不夠 //報告錯誤給用戶,清除Winsock,返回 WSACleanup(); return; }2.2 socket()
【函數原型】
SOCKET socket(int af, int type, int protocol);【參數】
af[in] 指定地址族(address family),一般填AF_INET(使用Internet地址)。type
[in] 指定SOCKET的類型:SOCK_STREAM(流類型),SOCK_DGRAM(數據報類型)。protocol
[in] 指定af參數指定的地址族所使用的具體一個協議。建議設為0,那么它就會根據地址格式和SOCKET類型,自動為你選擇一個合適的協議。另外2個常用的值為:IPPROTO_UDP和IPPROTO_TCP。
【返回值】
函數執行成功返回一個新的SOCKET,失敗則返回INVALID_SOCKET。這時可以調用WSAGetLastError函數取得具體的錯誤代碼。【函數功能】
所有的通信在建立之前都要創建一個SOCKET。【示例代碼】
//創建數據報socket SCOKET udpSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //創建流socket SCOKET tcpSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);2.3 bind()
【函數原型】
int bind(SOCKET s, const struct sockaddr FAR* name, int namelen);【參數】
s[in] 一個需要綁定的SOCKET,例如用socket函數創建的SOCKET。name
[in] 指向描述通信對象地址信息的結構體sockaddr的指針。在該結構體中可以指定地址族(一般為 AF_INET)、主機的地址和端口。通常把主機地址指定為INADDR_ANY(一個主機可能有多個網卡)。namelen
[in] name指針指向的結構體的長度。
【返回值】
函數執行成功返回0,失敗則返回SOCKET_ERROR。這時可以調用WSAGetLastError函數取得具體的錯誤代碼。【函數功能】
成功地創建了一個SOCKET后,用bind函數將SOCKET和主機地址綁定。【相關數據結構】
struct sockaddr { u_short sa_family; char sa_data[14]; }; sa_family地址族,比如AF_INET,2個字節大小。sa_data
用來存放地址和端口,14個字節大小。
sockaddr結構是一個通用的結構(因為Winsock支持的協議族不只是TCP/IP)。對TCP/IP協議,用如下結構來定義地址和端口。struct sockaddr_in { short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; sin_family
地址族,設為AF_INET。sin_port
端口號。如果端口號為0,Winsock會自動為應用程序分配一個值在1024-5000間的一個端口號,所以客戶端一般把sin_port設為0。sin_addr
為in_addr結構類型,用來指定IP地址。通常把主機地址指定為INADDR_ANY(一個主機可能有多個網卡)。結構in_addr下面介紹。sin_zero
8字節的數組,值全為0。這個8個字節用來填充結構sockaddr_in,使其大小等于結構sockaddr(16字節)。
結構in_addr用來指定IP地址,其定義為:
struct in_addr {union {struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;struct { u_short s_w1,s_w2; } S_un_w;u_long S_addr;} S_un; };對于IP地址10.14.25.90,sockaddr_in結構中的sin_addr可以這樣賦值:
sin_addr. S_un .S_un_b. s_b1 = 10; sin_addr. S_un .S_un_b. s_b2 = 14; sin_addr. S_un .S_un_b. s_b3 = 25; sin_addr. S_un .S_un_b. s_b4 = 90;或者
sin_addr. S_un . S_un_w. s_w1 = (14<<8)|10; sin_addr. S_un . S_un_w. s_w2 = (90<<8)|25;或者
sin_addr. S_un . S_addr = (90<<24)|(25<<16)|(14<<8)|10;或者
sin_addr. S_un . S_addr = inet_addr(“10.14.25.90”);這里的inet_addr函數可以將字符串形式的IP地址轉換為unsigned long形式的值。
【示例代碼】
SOCKET sServSock; sockaddr_in addr;//創建socket sServSock = socket(AF_INET, SOCK_STREAM, 0);addr.sin_family = AF_INET;//htons和htonl函數把主機字節順序轉換為網絡字節順序,分別用于//短整型和長整型數據 addr.sin_port = htons(5050); addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // LPSOCKADDR類型轉換是必須的 int nRc = bind(sServSock, (LPSOCKADDR)&addr, sizeof(addr) );2.4 listen()
【函數原型】
int listen (SOCKET s, int backlog);【參數】
s[in] 一個已經綁定但未連接的SOCKET。backlog
[in] 等待連接的隊列的長度,可取SOMAXCONN。如果某個客戶程序要求連接的時候,服務器已經與其他客戶程序連接,則后來的連接請求會放在等待隊列中,等待服務器空閑時再與之連接。當等待隊列達到最大長度(backlog指定的值)時,再來的連接請求都將被拒絕。
【返回值】
函數執行成功返回0,失敗則返回SOCKET_ERROR。這時可以調用WSAGetLastError函數取得具體的錯誤代碼。【函數功能】
對于服務器的程序,當申請到SOCKET,并將通信對象指定為INADDR_ANY之后,就應該等待一個客戶機的程序來要求連接,listen函數就是把一個SOCKET設置為這個狀態。2.5 accept()
【函數原型】
SOCKET accept (SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen );【參數】
s[in] 一個已經處于listen狀態的SOCKET。addr
[out] 指向sockaddr結構體的指針,里面包含了客戶端的地址和端口。addrlen
[out] int型指針,指向的內容為addr指針指向的結構體的長度。
【返回值】
如果函數執行成功,會建立并返回一個新的SOCKET來與對方通信,新建的SOCKET與原來的SOCKET(函數的第一個參數s)有相同的特性,包括端口號。原來的SOCKET繼續等待其他的連接請求。而新生成的SOCKET才是與客戶端通信的實際SOCKET。所以一般將參數中的SOCKET稱作“監聽”SOCKET,它只負責接受連接,不負責通話;而對于函數返回的SOCKET,把它稱作“會話”SOCKET,它負責與客戶端通話。如果失敗則返回INVALID_SOCKET。這時可以調用WSAGetLastError函數取得具體的錯誤代碼。
【函數功能】
accept函數從等待連接的隊列中取第一個連接請求,并且創建一個新的SOCKET來負責與客戶端會話。【示例代碼】
SOCKET sServSock; //服務器監聽socket sockaddr_in addr; int nSockErr; int nNumConns = 0; //當前請求連接數 SOCKET sConns[5]; //會話SOCKET數組 sockaddr ConnAddrs[5];//請求連接的客戶端地址 int nAddrLen;//創建服務器監聽socket sServSock = socket(AF_INET, SOCK_STREAM, 0);addr.sin_family = AF_INET; addr.sin_port = htons(5050); addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);if( bind(sServSock,(LPSOCKADDR)&addr,sizeof(addr)) == SOCKET_ERROR ) { nSockErr = WSAGetLastError(); //綁定出錯處理 } //監聽客戶端請求連接 if( listen(sServSock, 2) == SOCKET_ERROR) { nSockErr = WSAGetLastError(); //出錯處理 }while( nNumConns < 5){ //每當收到客戶端連接請求,創建新的會話SOCKET,保存在/ //sConns數組中 //客戶端地址保存在ConnAddrs數組中 sConns[nNumConns] = accept(sServSock, ConnAddrs[nNumConns], &nAddrLen); if(sConns[nNumConns] == INVALID_SOCKET) { nSockErr = WSAGetLastError(); //創建會話SOCKET出錯處理 } else { //創建會話SOCKET成功,啟動新的線程與客戶端會話 StartNewHandlerThread(sConns[nNumConns]); //當前請求連接數+1 nNumConns ++; } }2.6 connect()
【函數原型】
int connect (SOCKET s, const struct sockaddr FAR* name,int namelen );【參數】
s[in] 一個未連接SOCKET,一般是由socket函數建立的。name
[in] 同bind函數。namelen
[in] 同bind函數。
【返回值】
函數執行成功返回0,失敗則返回SOCKET_ERROR。這時可以調用WSAGetLastError函數取得具體的錯誤代碼。【函數功能】
向對方主動提出連接請求。2.7 send()
【函數原型】
int send (SOCKET s, char * buf, int len ,int flags);【參數】
s[in] 一個已經連接的SOCKET。buf
[in] 指向要傳輸的數據的緩沖區的指針。len
[in] buf的長度。flags
[in]指定函數調用的方式。一般取0。
【返回值】
函數執行成功返回發送的字節數(可能小于len),失敗則返回SOCKET_ERROR。這時可以調用WSAGetLastError函數取得具體的錯誤代碼。【函數功能】
通過已經連接的SOCKET發送數據。2.8 recv()
【函數原型】
int recv (SOCKET s, char * buf, int len ,int flags);【參數】
s[in] 一個已經連接的SOCKET。buf
[out] 指向接收數據的緩沖區的指針。len
[in] buf的長度。flags
[in]指定函數調用的方式。一般取0。
【返回值】
函數執行成功返回接收到數據的字節數。如果失敗則返回SOCKET_ERROR。這時可以調用WSAGetLastError函數取得具體的錯誤代碼。【函數功能】
通過已經連接的SOCKET接收數據。當讀到的數據字節少于規定接受的數目(len)時,就把數據全部接收,并返回實際接收到的字節數;當讀到的數據多于規定的值時,在流方式下剩余的數據由下個recv讀出,在數據報方式下多余的數據被丟棄。2.9 sendto()
【函數原型】
int sendto (SOCKET s, char * buf, int len ,int flags, struct sockaddr_in * to, int tolen);【參數】
s[in] 一個SOCKET(可能已連接)。buf
[in] 指向要傳輸的數據的緩沖區的指針。len
[in] buf的長度。flags
[in] 指定函數調用的方式。一般取0。to
[in] 指向目標地址結構體的指針。tolen
[in] 目標地址結構體的長度。
【返回值】
函數執行成功返回發送的字節數(可能小于len),失敗則返回SOCKET_ERROR。這時可以調用WSAGetLastError函數取得具體的錯誤代碼。【函數功能】
該函數一般用于通過無連接的SOCKET發送數據報文,報文的接受者由to參數指定。2.10 recvfrom()
【函數原型】
int recvfrom (SOCKET s, char * buf, int len ,int flags, struct sockaddr_in * from, int * fromlen);【參數】
s[in] 一個已經綁定的SOCKET。buf
[out] 指向接收數據的緩沖區的指針。len
[in] buf的長度。flags
[in] 指定函數調用的方式。一般取0。from
[out] 指向源地址結構體的指針。fromlen
[in/out] 源地址結構體的長度。
【返回值】
函數執行成功返回發送的字節數(可能小于len),失敗則返回SOCKET_ERROR。這時可以調用WSAGetLastError函數取得具體的錯誤代碼。【函數功能】
該函數一般用于通過無連接的SOCKET接收數據報文,報文的發送者由from參數指定。2.11 closesocket()
【函數原型】
int closesocket (SOCKET s,);【參數】
s[in] 要關閉的SOCKET。
【返回值】
函數執行成功返回0,失敗則返回SOCKET_ERROR。這時可以調用WSAGetLastError函數取得具體的錯誤代碼。【函數功能】
關閉指定的SOCKET。總結
以上是生活随笔為你收集整理的qt socket 传递结构体 结构体中有list_计算机网络应用--Socket编程实验(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tif文件转pdf_PPT怎么转换成PD
- 下一篇: python方差特征选择_使用sciki