日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Winsock网络编程快速入门

發布時間:2023/12/18 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Winsock网络编程快速入门 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


一、基本知識

?

1、Winsock,一種標準API,一種網絡編程接口,用于兩個或多個應用程序(或進程)之間通過網絡進行數據通信。具有兩個版本:

Winsock 1:

Windows CE平臺支持。

頭文件:WinSock.h

庫:wsock32.lib

?

Winsock 2:

部分平臺如Windows CE貌似不支持。通過前綴WSA可以區別于Winsock 1版本。個別函數如WSAStartup、WSACleanup、WSARecvEx、WSAGetLastError都屬于Winsock 1.1規范的函數;

頭文件:WinSock2.h

庫:ws2_32.lib

?

mswsock.h用于編程擴展,使用時必須鏈接mswsock.dll。

?

2、網絡協議:

IP (Internet Protocol)? 網際協議,無連接協議;

TCP (Transmission Control Protocol)? 傳輸控制協議;

UDP (User Datagram Protocol)? 用戶數據協議;

FTP (File Transfer Protocol)? 文件傳輸協議;

HTTP (Hypertext Transfer Protocol)? 超文本傳輸協議;

?

3、字節存儲順序:

big_endian:大端存儲,存儲順序從高位到低位,地址指向最高有效字節。在網絡中將IP和端口指定為多字節時使用大端存儲,也稱為網絡字節順序(network_byte)。貌似MAC OS使用的是大端存儲方式;

?

little_endian:小端存儲,存儲順序從低位到高位,地址指向最低有效字節。本地主機存儲IP和端口制定的多字節時使用,也稱為主機字節順序(host_byte)。大多數系統都是小端存儲;

?

用下面的方式可以檢測是否為大端存儲:

print?

bool IsBig_endian()?

{?

??? unsigned short test = 0x1122;?

??? if ( *( (unsigned char*)&test ) == 0x11 )?

??? {?

??????? return true;?

??? }??

??? else?

??? {?

??????? return false;?

??? }?

}?

?

此外有很多函數可以用來進行 主機字節和網絡字節之間的轉換,如:

u_long htonl( u_long hostlong );

int WSAHtonl( SOCKET s, u_long hostlong, u_long FAR *lpnetlong );

而有時網絡IP是點分法表示的,如:192.168.0.1,使用函數unsigned long inet_addr( const char FAR *cp ); 可以將點分法的IP字符串作為一個網絡字節順序的32位u_long返回。

?

?

二、快速了解

?

1、Winsock初始化:

首先確保包含對應版本的頭文件,然后保證鏈接對應的庫文件(可以在代碼中使用#pragma comment(lib, "WS2_32"),或在編譯器項目屬性中鏈接器->輸入->附加依賴項中添加ws2_32.lib);

?通過調用WSAStartup函數來實現加載Winsock庫:

print?

int?

WSAAPI?

WSAStartup(?

??? IN WORD wVersionRequested,?

??? OUT LPWSADATA lpWSAData?

??? );?

其中參數wVersionRequested用來指定加載Winsock庫的版本,高位字節為次版本,低位字節為主版本,使用宏MAKEWORD(x,y)來生成一個WORD;

參數lpWSAData是指向WASDATA結構指針,加載的版本庫信息將會填充這個結構,詳細內容自查。

在使用Winsock后需要釋放資源,并取消應用程序掛起的Winsock操作。使用int WASCleanup();

?

?

2、錯誤處理:

如果已經加載了Winsock庫,則調用Winsock函數出錯后,通常會返回SOCKET_ERROR,而通過使用函數int WSAGetLastError() 可以獲得具體信息值,例如:

print?

if ( SOCKET_ERROR == WSACleanup() )?

{?

??? cout << "WSACleanup error " << WSAGetLastError() << endl;?

??? return 0;?

}?

根據獲取錯誤信息值,可以知道錯誤原因,并進行相應的處理。

?

?

3、尋址:

想要進行通信就需要知道彼此的地址,一般來說這個地址由IP和端口號來決定。在Winsock中使用SOCKADDR_IN結構來指定地址信息:

print?

struct sockaddr_in {?

??????? short?? sin_family;?

??????? u_short sin_port;?

??????? struct? in_addr sin_addr;?

??????? char??? sin_zero[8];?

};?

sin_family字段通常設置為AF_INET,表示Winsock此時正在使用IP地址族;

sin_port用于標示TCP或UDP通信端口,部分端口是為一些服務保留的,如FTP和HTTP使用要注意;

sin_adr字段把地址(例如是IPv4地址)作為一個4字節的量來存儲起來,它是u_long類型,且是網絡字節順序的。可以使用inet_addr來處理點分法表示的IP地址;

sin_zero只充當填充項,以使SOCKADDR_IN結構和SOCKADDR結構長度一樣。

以下簡單的使用SOCKADDR_IN來指定地址:

print?

//創建一個地址?

int serverPort????? = 5150;?

?

char FAR serverIP[] = "192.168.1.102"; //本機ip,不知道就ipconfig?

?

SOCKADDR_IN serverAddr;?

serverAddr.sin_family?? = AF_INET;?

serverAddr.sin_port = htons( serverPort );?

serverAddr.sin_addr.s_addr? = inet_addr( serverIP );?

int serverAddr_size = static_cast<int>( sizeof(serverAddr) );?

有時作為一個連接通信的服務端來說,在設置監聽socket的地址結構時sin_addr.s_addr的值可以是htonl( INADDR_ANY ),INADDR_ANY允許將socket綁定到系統中所有可用的接口,以便傳到任意接口的連接(端口必須正確)都可以被監聽socket接受。

?

?

4、socket套接字:

套接字是通信時為傳輸提供的句柄,Winsock的操作都是基于套接字實現的。創建一個套接字有socket和WSASocket方法:

print?

SOCKET?

WSAAPI?

socket(?

?????? IN int af,?????? //協議的地址族,使用IPv4來描述Winsock,設置為AF_INET?

?????? IN int type,???? //套接字類型,TCP/IP設置為SOCK_STREAM,UDP/IP設置為SOCK_DGRAM?

?????? IN int protocol????? //用于給定地址族和類型具有多重入口的傳送限定,TCP設置為IPPROTO_TCP,UDP設置為IPPROTO_UDP?

?????? );?

如果創建成功,函數會返回一個有效的SOCKET,否則會返回INVALID_SOCKET,可以用WSAGetLastError()函數獲得錯誤信息。

?

?

5、連接通信實現過程:

連結通信是基于TCP/IP實現的,進行數據傳輸前,通信雙方要進行連接。

?

服務端:

初始化Winsock后,創建一個監聽socket和一個要接受連接的地址結構;

使用bind將監聽socket與地址結構進行關聯;

print?

int?

WSAAPI?

bind(?

???? IN SOCKET s,?????????????? //一個用于監聽的socket?

???? IN const struct sockaddr FAR * name,?? //指向進行綁定的地址結構?

???? IN int namelen???????????? //進行綁定的地址結構的大小?

???? );?

使用listen將bind成功的監聽socket狀態設置為監聽狀態;

print?

int?

WSAAPI?

listen(?

?????? IN SOCKET s, ????//一個用于監聽的socket,已經進行bind?

?????? IN int backlog?????? //允許掛起連接的隊列的最大長度,超過這個長度后,再有連接將會失敗?

?????? );?

?

使用accept接受通過監聽socket獲取的連接,成功后將返回的新的連接socket進行保存以便數據傳輸;

print?

SOCKET?

WSAAPI?

accept(?

?????? IN SOCKET s,???????? //處于監聽模式的socket?

?????? OUT struct sockaddr FAR * addr,? //指向一個地址結構,用來接受連接后獲得對方地址信息?

?????? IN OUT int FAR * addrlen???? //指向一個整數,表示參數2指向地址結構的大小?

?????? );?

?

?

客戶端:

初始化Winsock后,創建一個監聽socket和一個要連接的服務器地址結構;

使用connect將socket和服務器地址結構進行初始化連接,成功后將使用socket進行數據傳輸;

print?

int?

WSAAPI?

connect(?

??????? IN SOCKET s,??????????? //要建立連接的socket?

??????? IN const struct sockaddr FAR * name,??? //指向保存要建立連接信息的地址結構?

??????? IN int namelen????????? //參數2指向地址結構的大小?

??????? );?

?

?

連接成功后,使用send、recv來進行數據傳輸;

print?

int?

WSAAPI?

send(?

???? IN SOCKET s,?????? //進行連接的socket?

???? IN const char FAR * buf,?? //指向發送數據的緩沖區?

???? IN int len,??????? //發送數據的字符數?

???? IN int flags?????? //一個標志位,可以是0、MSG_DONTROUTE、MSG_OOB還可以是他們的或運算結果?

???? );???????? //返回已經發送的數據長度?

?

?

int?

WSAAPI?

recv(?

???? IN SOCKET s,?????? //進行連接的socket?

???? OUT char FAR * buf,??? //指向接受數據的緩沖區?

???? IN int len,??????? //準備接受數據字節數或緩沖區的長度?

???? IN int flags?????? //可以是0、MSG_PEEK、MSG_OOB還可以是他們的或運算結果?

???? );???????? //返回已接受的數據長度?

?

連接結束后,使用shutdown和closesocket來斷開連接和釋放資源;

print?

int?

WSAAPI?

shutdown(?

???????? IN SOCKET s,?? //要關閉的socket?

???????? IN int how //關閉標志:SD_RECEIVE、SD_SEND、SD_BOTH?

???????? );?

?

?

6、無連接通信實現過程:

無連接通信是基于UDP/IP實現的,UDP不能確保可靠的數據傳輸,但能將數據發送到多個目標,或者接受多個源的數據。

初始化Winsock后,可以創建socket和用以進行通信任意地址結構;

使用recvfrom通過socket和通信的地址結構接受數據;

使用sendto通過socket和通信的地址結構發送數據;

print?

int?

WSAAPI?

recvfrom(?

???????? IN SOCKET s,?

???????? OUT char FAR * buf,?

???????? IN int len,?

???????? IN int flags,?

???????? OUT struct sockaddr FAR * from,?

???????? IN OUT int FAR * fromlen?

???????? );?

?

int?

WSAAPI?

sendto(?

?????? IN SOCKET s,?

?????? IN const char FAR * buf,?

?????? IN int len,?

?????? IN int flags,?

?????? IN const struct sockaddr FAR * to,?

?????? IN int tolen?

?????? );?

?

同樣通信結束后,使用shutdown和closesocket來斷開連接和釋放資源

?

?

上述使用函數都有多個版本,而且相關的一些標志位參數可以提供設置選項,另外,返回的錯誤處理等也有待于詳細研究;

?

?

7、select函數:

?

select()用于確定一個或多個套接口的狀態。對每一個套接口,調用者可查詢它的可讀性、可寫性及錯誤狀態信息。

print?

int?

WSAAPI?

select(?

?????? IN int nfds,???????? //指集合中所有文件描述符的范圍,即所有文件描述符的最大值加1,在Windows中值無所謂。??

?????? IN OUT fd_set FAR * readfds, //可選指針,指向一組等待可讀性檢查的套接字。??

?????? IN OUT fd_set FAR * writefds,??? //可選指針,指向一組等待可寫性檢查的套接字。?

?????? IN OUT fd_set FAR *exceptfds,??? //可選指針,指向一組等待錯誤檢查的套接字。?

?????? IN const struct timeval FAR * timeout??? //select()最多等待時間,對阻塞操作則為NULL。?

?????? );?

?

//用fd_set結構來表示一組等待檢查的套接口。在調用返回時,這個結構存有滿足一定條件的套接口組的子集:?

?

typedef struct fd_set {?

??? u_int fd_count;?????????????? //其中set元素數目?

??? SOCKET? fd_array[FD_SETSIZE]; //保存set元素的數組?

} fd_set;?

?

fd_set set;?

FD_ZERO(&set);????? /*將set清零使集合中不含任何fd*/   ?

FD_SET(fd, &set);?????? /*將fd加入set集合*/   ?

FD_CLR(fd, &set);?????? /*將fd從set集合中清除*/   ?

FD_ISSET(fd, &set);???? /*測試fd是否在set集合中*/??

?

select的返回值:

select()調用返回處于就緒狀態并且已經包含在fd_set結構中的描述字總數;

如果超時則返回0;否則的話,返回SOCKET_ERROR錯誤,通過WSAGetLastError獲取相應錯誤代碼。

當返回位0時,所有描述符集清0;

當返回為-1時,不修改任何描述符集;

當返回為非0時,在3個描述符集里,依舊是1的位就是準備好的描述符。這也就是為什么,每次用select后都要用FD_ISSET的原因。

?

?

三、簡單實踐

?

利用上述內容,實現一個基于TCP/IP的連接通信。

?

服務端:

?

//******************************************************************

print?

#include "stdafx.h"?

?

#include <iostream>?

?

#include <WinSock2.h>?

?

#pragma comment(lib, "WS2_32")?

?

?

using namespace std;?

?

?

?

# define REQUEST_BACKLOG 5?

?

?

//******************************?

//好吧不用寫這些糾結的函數,就是看著清晰些?

//初始化Winsock?

bool InitWSA( const WORD &wVersion, WSADATA *wsadata )?

{?

??? int Ret = 0;?

??? if ( ( Ret = WSAStartup( wVersion,wsadata ) ) != 0 )?

??? {?

??????? cout << "WSAStartup failed, error "? << Ret << endl;?

?

??????? return false;?

??? }?

?

??? return true;?

}?

?

?

//結束Winsock?

void cleanWSA()?

{?

??? if ( WSACleanup() == SOCKET_ERROR )?

??? {?

??????? cout << "WSACleanup failed, error "? << WSAGetLastError() << endl;?

??? }?

}?

?

?

?

//IPv4尋址,通過ip填充SOCKADDR_IN結構?

void InitSockAddrByIP( SOCKADDR_IN *pSockAddr, const char FAR *strIP, const INT &nPortID )?

{?

??? pSockAddr->sin_family??????????? = AF_INET;?

?

??? pSockAddr->sin_port????????????? = htons( nPortID );?

?

??? if ( 0 != strlen(strIP) )?

??? {?

??????? pSockAddr->sin_addr.s_addr?????? = inet_addr( strIP );?

??? }?

??? else?

??? {?

??????? pSockAddr->sin_addr.s_addr?????? = htonl( INADDR_ANY );?

??? }?

}?

?

?

//bind?

bool bindAddr( const SOCKADDR_IN *pSockAddr, SOCKET *pSocket )?

{?

??? int bindResult = bind( *pSocket, (sockaddr *)(pSockAddr), sizeof(*pSockAddr));?

?

??? if ( SOCKET_ERROR == bindResult )?

??? {?

??????? cout << "bind error :" << WSAGetLastError() << endl;?

??????? return false;?

??? }??

??? return true;?

}?

?

?

//listen?

bool setListener( SOCKET *pSocket, int backlog )?

{?

??? int nResult = listen( *pSocket, backlog );?

?

??? if ( SOCKET_ERROR == nResult )?

??? {?

??????? cout << "listen error :" << WSAGetLastError() << endl;?

??????? return false;?

??? }??

??? return true;?

}?

?

?

?

?

?

//******************************?

?

?

//程序入口?

int _tmain(int argc, _TCHAR* argv[])?

{?

?

??? //初始化Winsock?

??? WSADATA wsadata;?

??? if ( !InitWSA( MAKEWORD(2,2), &wsadata ) )?

??? {?

??????? return 0;?

??? }?

?

?

??? //指定連接ip地址和服務器口?

?

??? SOCKADDR_IN InternetAddr;?

??? //char FAR strIP[]? = "198.0.0.0";?

??? char FAR strIP[]??? = "";?

??? INT nPortID???????? = 5150;?

??? InitSockAddrByIP( &InternetAddr, strIP, nPortID );?

?

?

?

??? //創建listener_socket?

??? SOCKET listener_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );?

??? if ( INVALID_SOCKET == listener_socket )?

??? {?

??????? cout << "listener_socket creat failed " << endl;?

??????? return 0;?

??? }?

?

?

??? //bind?

??? if ( !bindAddr( &InternetAddr, &listener_socket ) )?

??? {?

??????? return 0;?

??? }?

?

?

??? //監聽?

??? if ( !setListener( &listener_socket, REQUEST_BACKLOG ) )?

??? {?

??????? return 0;?

??? }?

?

??? cout << "server started~~~ " << endl;?

?

?

?

??? //創建socket保存結構?

??? fd_set fdSocket;?

??? FD_ZERO( &fdSocket );?

??? FD_SET( listener_socket, &fdSocket );?

?

?

??? //查找可讀的socket?

??? while( true )?

??? {?

??????? fd_set fdSocket_temp;?

??????? fdSocket_temp = fdSocket;?

?????????

??????? fd_set fdRead;?

??????? fdRead = fdSocket;?

?

??????? fd_set fdExceptds;?

??????? fdExceptds = fdSocket;?

?

??????? int nResult_select = select( 0, &fdRead, NULL, &fdExceptds, NULL );?

?

??????? if ( 0 < nResult_select )?

??????? {?

??????????? unsigned int socket_count = fdSocket_temp.fd_count;?

??????????? for ( unsigned int i=0; i< socket_count; i++ )?

??????????? {?

?

??????????????? //可讀的?

?

??????????????? if ( FD_ISSET( fdSocket_temp.fd_array[i], &fdRead ) )?

??????????????? {?

??????????????????? //找到所有可讀連接?

??????????????????? if ( fdSocket_temp.fd_array[i] == listener_socket )?

??????????????????? {?

??????????????????????? if ( fdSocket.fd_count < FD_SETSIZE )?

??????????????????????? {?

?

?????????????????????????

??????????????????????????? //接受新的連接?

???????????????????? ???????SOCKADDR_IN ClientAddr;?

??????????????????????????? int addrlen = static_cast<int>(sizeof(ClientAddr));?? //一定要賦值?

?

??????????????????????????? SOCKET newClient_socket = accept( listener_socket, (sockaddr *)&ClientAddr, &addrlen );?

????????? ??????????????????if ( INVALID_SOCKET == newClient_socket )?

??????????????????????????? {?

??????????????????????????????? cout << " accept error " << WSAGetLastError() << endl;?

??????????????????????????? }?

??????????????????????????? else?

????? ??????????????????????{?

??????????????????????????????? FD_SET( newClient_socket, &fdSocket );?

??????????????????????????????? cout << "find new connect: " << inet_ntoa( ClientAddr.sin_addr ) << endl;?

??????????????????????????? }?

??????????????????????? }?

?

??????????????????????? else?

??????????????????????? {?

??????????????????????????? cout<<"too much connections"<<endl;?

??????????????????????????? continue;?

??????????????????????? }?

?

??????????????????? }??

??? ????????????????else?

??????????????????? {?

?

??????????????????????? //接收數據?

?

??????????????????????? char recvbuff[1024];?

??????????????????????? int? ret = 0;?

?

??????????????????????? ret = recv( fdSocket_temp.fd_array[i], recvbuff, static_cast<int>( strlen(recvbuff) ), 0 );?

??????????????????????? if ( 0 < ret )?

??????????????????????? {?

??????????????????????????? recvbuff[ret] = '\0';?

??????????????????????????? cout << "recv : " << recvbuff << endl;?

??????????????????????????? //回復?

??????????????????????????? char backbuf[1024] = "receive info!";?

??????????????????????????? send( fdSocket_temp.fd_array[i], backbuf, static_cast<int>( strlen(backbuf) ), 0 );?

?????????????

??????????????????????? }?

??????????????????????? else?

??????????????????????? {?

??????????????????????????? //該連接斷開?

??????????????????????????? closesocket( fdSocket_temp.fd_array[i] );?

??????????????????????????? FD_CLR( fdSocket_temp.fd_array[i], &fdSocket );?

???????? ???????????????}?

?

??????????????????? }?

?????????????????????

??????????????? }?

??????????????? else if( fdSocket_temp.fd_array[i] != listener_socket )?

??????????????? {?

??????????????????? //該連接斷開?

??????????????????? closesocket( fdSocket_temp.fd_array[i] );?

??????????????????? FD_CLR( fdSocket_temp.fd_array[i], &fdSocket );?

??????????????? }?

?

?

??????????????? if ( FD_ISSET( fdSocket_temp.fd_array[i], &fdExceptds )? &&? (fdSocket_temp.fd_array[i] != listener_socket) )?

?????????? ?????{?

??????????????????? //該連接斷開?

??????????????????? closesocket( fdSocket_temp.fd_array[i] );?

??????????????????? FD_CLR( fdSocket_temp.fd_array[i], &fdSocket );?

??????????????? }?

?????

??????????? }//end for?

??????? }?

?

?

??????? else if( SOCKET_ERROR == nResult_select )?

??????? {?

??????????? cout << "select error : " << WSAGetLastError() << endl;?

??????????? return 0;?

??????? }?

?

?

??????? Sleep( 50 );??? //不要挑戰你的機器?

?

??? }//end while?

?

?

??? closesocket( listener_socket );?

??? cleanWSA();?

?

??? return 0;?

}?

?

?

?

客戶端:

?

//******************************************************************

print?

#include "stdafx.h"?

?

#include <WinSock2.h>?

?

#include <iostream>?

?

#pragma comment(lib, "WS2_32")?

?

using namespace std;?

?

?

?

?

int _tmain(int argc, _TCHAR* argv[])?

{?

??? int result = 0;?

?

??? //初始化winsock?

?

??? WSADATA wsadata;?

??? result = WSAStartup( MAKEWORD(2,2), &wsadata );?

?

??? if ( 0 != result )?

??? {?

??????? cout << "WSAStartup error " << result << endl;?

??????? return 0;?

??? }?

?

??? //創建一個地址?

??? int serverPort????? = 5150;?

?

??? char FAR serverIP[] = "192.168.1.102"; //本機ip,不知道就ipconfig?

?

??? SOCKADDR_IN serverAddr;?

??? serverAddr.sin_family?????? = AF_INET;?

??? serverAddr.sin_port???????? = htons( serverPort );?

??? serverAddr.sin_addr.s_addr? = inet_addr( serverIP );?

??? int serverAddr_size???????? = static_cast<int>( sizeof(serverAddr) );?

?

??? //創建一個socket?

??? SOCKET socket_toServer;?

??? socket_toServer = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );?

??? if ( INVALID_SOCKET == socket_toServer )?

??? {?

??????? cout << "socket_toServer creat failed " << WSAGetLastError() << endl;?

??????? return 0;?

??? }?

?

?????

??? //連接?

??? result = connect( socket_toServer, (sockaddr *)&serverAddr, serverAddr_size );?

??? if ( SOCKET_ERROR == result )?

??? {?

??????? cout << "connect error :" << WSAGetLastError() << endl;?

??????? return 0;?

??? }?

?

?????

??? char sendbuff[2048];?

??? char recvbuff[2048];?

?

??? while( true )?

??? {?

??????? cout << "input send info:" << endl;?

??????? cin >> sendbuff;?

?

??????? int ret = send( socket_toServer, sendbuff, static_cast<int>( strlen(sendbuff) ), 0 );?

??????? if ( SOCKET_ERROR == ret )?

??????? {?

??????????? cout << "send error " << WSAGetLastError() <<? endl;?

??????????? break;?

??????? }?

?

??????? //處理接受的消息,由于之前沒有accept和listen,這里使用recvfrom來接受?

??????? int nRecv = 0;?

??????? nRecv = recvfrom( socket_toServer, recvbuff, static_cast<int>( strlen(recvbuff) ), 0, (sockaddr *)&serverAddr, &serverAddr_size );?

??????? if ( 0 < nRecv )?

??????? {?

?? ?????????recvbuff[nRecv] = '\0';?

??????????? cout << "receive : " << recvbuff << endl;?

??????????? cout << "from : " << inet_ntoa( serverAddr.sin_addr ) << endl;?

??????????? cout << " " << endl;?

??????? }?

??? }?

?

?

??? //清除各種數據和鏈接?

?

??? closesocket( socket_toServer );?

?

??? if ( SOCKET_ERROR == WSACleanup() )?

??? {?

??????? cout << "WSACleanup error " << WSAGetLastError() << endl;?

??????? return 0;?

??? }?

?????

?

??? return 0;?

}?

總結

以上是生活随笔為你收集整理的Winsock网络编程快速入门的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。