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