C++网络编程:Winsock2.h环境下Socket套接字应用教程

更新:11-17 民间故事 我要投稿 纠错 投诉

服务器

初始化Winsock。创建套接字。绑定套接字。监听套接字上的客户端。接受来自客户端的连接。接收和发送数据。断开连接

客户端

初始化Winsock。创建套接字。连接到该服务器。发送和接收数据。断开很明显,1、2、断开是完全一样的步骤

0.检测环境

使用vs,调试以下代码,确定环境是否准备充分。

#include#include#include#pragma comment(lib, "Ws2_32.lib")

int main() {

printf("你好世界");

返回0;

}

1. 初始化

#include#include#include#pragma 注释(lib, "Ws2_32.lib")

int main() {

WSADATA wsaData;

int iResult;

iResult=WSAStartup(MAKEWORD(2, 2), wsaData);

if (iResult !=0) {

printf("WSA启动失败: %dn", iResult);

返回1;

}

printf("你好世界");

返回0;

}

2. 服务器端创建套接字

首先为服务端创建一个socket,以便后续的客户端可以连接调试

#include#include#include#pragma comment(lib, "Ws2_32.lib")

#define DEFAULT_PORT "9501" //服务器监听的端口

int main() {

//1.初始化开始

WSADATA wsaData;

int iResult;

iResult=WSAStartup(MAKEWORD(2, 2), wsaData);

if (iResult !=0) {

printf("WSA启动失败: %dn", iResult);

返回1;

}

//1.初始化结束

//2.创建socket启动

结构地址信息*

结果=空,

*ptr=NULL,

提示;

ZeroMemory(提示, sizeof(提示));

提示.ai_family=AF_INET; //AF _INET用于指定IPv4地址族

提示.ai_socktype=SOCK_STREAM; //SOCK _STREAM 用于指定流套接字

提示.ai_protocol=IPPROTO_TCP; //IPPROTO _TCP 用于指定tcp协议

提示.ai_flags=AI_PASSIVE;

//从本机获取IP地址等信息供sockce使用

iResult=getaddrinfo(NULL, DEFAULT_PORT, 提示, 结果);

if (iResult !=0) {

printf("getaddrinfo failed: %dn", iResult);

WSACleanup();

返回1;

}

//创建套接字对象

SOCKET ListenSocket=INVALID_SOCKET;

ListenSocket=套接字(结果-ai_family, 结果-ai_socktype, 结果-ai_protocol);

如果(ListenSocket==INVALID_SOCKET){

printf("socket(): %ldn 出错", WSAGetLastError());

freeaddrinfo(结果);

WSACleanup();

返回1;

}

//2.创建socket端

返回0;

}尝试调试每一步,检查是否有错误。

3.绑定套接字

要使服务器接受客户端连接,它必须绑定到服务器的网络地址。

#include#include#include#pragma comment(lib, "Ws2_32.lib")

#define DEFAULT_PORT "9501" //服务器监听的端口

int main() {

//1.初始化开始

WSADATA wsaData;

int iResult;

iResult=WSAStartup(MAKEWORD(2, 2), wsaData);

if (iResult !=0) {

printf("WSA启动失败: %dn", iResult);

返回1;

}

//1.初始化结束

//2.创建socket启动

结构地址信息*

结果=空,

*ptr=NULL,

提示;

ZeroMemory(提示, sizeof(提示));

提示.ai_family=AF_INET; //AF _INET用于指定IPv4地址族

提示.ai_socktype=SOCK_STREAM; //SOCK _STREAM 用于指定流套接字

提示.ai_protocol=IPPROTO_TCP; //IPPROTO _TCP 用于指定tcp协议

提示.ai_flags=AI_PASSIVE;

//从本机获取IP地址等信息供sockce使用

iResult=getaddrinfo(NULL, DEFAULT_PORT, 提示, 结果);

if (iResult !=0) {

printf("getaddrinfo failed: %dn", iResult);

WSACleanup();

返回1;

}

//创建套接字对象

SOCKET ListenSocket=INVALID_SOCKET;

ListenSocket=套接字(结果-ai_family, 结果-ai_socktype, 结果-ai_protocol);

如果(ListenSocket==INVALID_SOCKET){

printf("socket(): %ldn 出错", WSAGetLastError());

freeaddrinfo(结果);

WSACleanup();

返回1;

}

//2.创建socket端

//3. 绑定套接字启动

iResult=bind(ListenSocket, 结果-ai_addr, (int)结果-ai_addrlen);

如果(iResult==SOCKET_ERROR){

printf("绑定失败,错误: %dn", WSAGetLastError());

freeaddrinfo(result);//调用bind函数后,不再需要地址信息。发布

关闭套接字(ListenSocket);

WSACleanup();

返回1;

}

//3.绑定socket端

返回0;

}

4.在套接字上监听客户端

将套接字绑定到系统上的IP 地址和端口后,服务器必须侦听该IP 地址和端口以接收传入的连接请求

#include#include#include#pragma comment(lib, "Ws2_32.lib")

#define DEFAULT_PORT "9501" //服务器监听的端口

int main() {

//1.初始化开始

WSADATA wsaData;

int iResult;

iResult=WSAStartup(MAKEWORD(2, 2), wsaData);

if (iResult !=0) {

printf("WSA启动失败: %dn", iResult);

返回1;

}

//1.初始化结束

//2.创建socket启动

结构地址信息*

结果=空,

*ptr=NULL,

提示;

ZeroMemory(提示, sizeof(提示));

提示.ai_family=AF_INET; //AF _INET用于指定IPv4地址族

提示.ai_socktype=SOCK_STREAM; //SOCK _STREAM 用于指定流套接字

提示.ai_protocol=IPPROTO_TCP; //IPPROTO _TCP 用于指定tcp协议

提示.ai_flags=AI_PASSIVE;

//从本机获取IP地址等信息供sockce使用

iResult=getaddrinfo(NULL, DEFAULT_PORT, 提示, 结果);

if (iResult !=0) {

printf("getaddrinfo failed: %dn", iResult);

WSACleanup();

返回1;

}

//创建套接字对象

SOCKET ListenSocket=INVALID_SOCKET;

ListenSocket=套接字(结果-ai_family, 结果-ai_socktype, 结果-ai_protocol);

如果(ListenSocket==INVALID_SOCKET){

printf("socket(): %ldn 出错", WSAGetLastError());

freeaddrinfo(结果);

WSACleanup();

返回1;

}

//2.创建socket端

//3. 绑定套接字启动

iResult=bind(ListenSocket, 结果-ai_addr, (int)结果-ai_addrlen);

如果(iResult==SOCKET_ERROR){

printf("绑定失败,错误: %dn", WSAGetLastError());

freeaddrinfo(result);//调用bind函数后,不再需要地址信息。发布

关闭套接字(ListenSocket);

WSACleanup();

返回1;

}

//3.绑定socket端

//4.监听客户端在socket上的启动

if (listen(ListenSocket, SOMAXCONN)==SOCKET_ERROR) {

//SOMAXCONN定义了该socket允许的最大连接数

printf("监听失败,错误: %ldn", WSAGetLastError());

关闭套接字(ListenSocket);

WSACleanup();

返回1;

}

//4.在socket端监听客户端

返回0;

}备注: 调试Windows 10 的第一步将要求用户授予防火墙权限。

5. 接受来自客户端的连接。

套接字侦听连接后,程序必须处理该套接字上的连接请求

#include#include#include#pragma comment(lib, "Ws2_32.lib")

#define DEFAULT_PORT "9501" //服务器监听的端口

int main() {

//1.初始化开始

WSADATA wsaData;

int iResult;

iResult=WSAStartup(MAKEWORD(2, 2), wsaData);

if (iResult !=0) {

printf("WSA启动失败: %dn", iResult);

返回1;

}

//1.初始化结束

//2.创建socket启动

结构地址信息*

结果=空,

*ptr=NULL,

提示;

ZeroMemory(提示, sizeof(提示));

提示.ai_family=AF_INET; //AF _INET用于指定IPv4地址族

提示.ai_socktype=SOCK_STREAM; //SOCK _STREAM 用于指定流套接字

提示.ai_protocol=IPPROTO_TCP; //IPPROTO _TCP 用于指定tcp协议

提示.ai_flags=AI_PASSIVE;

//从本机获取IP地址等信息供sockce使用

iResult=getaddrinfo(NULL, DEFAULT_PORT, 提示, 结果);

if (iResult !=0) {

printf("getaddrinfo failed: %dn", iResult);

WSACleanup();

返回1;

}

//创建套接字对象

SOCKET ListenSocket=INVALID_SOCKET;

ListenSocket=套接字(结果-ai_family, 结果-ai_socktype, 结果-ai_protocol);

如果(ListenSocket==INVALID_SOCKET){

printf("socket(): %ldn 出错", WSAGetLastError());

freeaddrinfo(结果);

WSACleanup();

返回1;

}

//2.创建socket端

//3. 绑定套接字启动

iResult=bind(ListenSocket, 结果-ai_addr, (int)结果-ai_addrlen);

如果(iResult==SOCKET_ERROR){

printf("绑定失败,错误: %dn", WSAGetLastError());

freeaddrinfo(result);//调用bind函数后,不再需要地址信息。发布

关闭套接字(ListenSocket);

WSACleanup();

返回1;

}

//3.绑定socket端

//4.监听客户端在socket上的启动

if (listen(ListenSocket, SOMAXCONN)==SOCKET_ERROR) {

//SOMAXCONN定义了该socket允许的最大连接数

printf("监听失败,错误: %ldn", WSAGetLastError());

关闭套接字(ListenSocket);

WSACleanup();

返回1;

}

//4.在socket端监听客户端

//5. 从客户端开始接受连接

SOCKET 客户端套接字; //用于接受来自客户端的连接的临时套接字对象

//这里不考虑多线程同时接受多个客户端。仅接受一项。

ClientSocket=接受(ListenSocket, NULL, NULL);

如果(ClientSocket==INVALID_SOCKET){

printf("接受失败: %dn", WSAGetLastError());

关闭套接字(ListenSocket);

WSACleanup();

返回1;

}

//5.接受客户端的连接

返回0;

}Remark : 运行此步骤时,控制台似乎没有显示任何内容。实际上accept阻塞了逻辑流程,等待客户端连接,如下图所示。

接受块逻辑流

6.在服务器上接收和发送数据

。服务器接收的数据来自客户端,发送也是向客户端发送数据。因此,需要等待下面的客户端socket写入之后才能进行最终的功能测试。

#include#include#include#pragma comment(lib, "Ws2_32.lib")

int main() {

//1.初始化开始

WSADATA wsaData;

int iResult;

iResult=WSAStartup(MAKEWORD(2, 2), wsaData);

if (iResult !=0) {

printf("WSA启动失败: %dn", iResult);

返回1;

}

//1.初始化结束

//2.创建socket启动

#define DEFAULT_PORT "9501" //服务器监听的端口

结构地址信息*

结果=空,

*ptr=NULL,

提示;

ZeroMemory(提示, sizeof(提示));

提示.ai_family=AF_INET; //AF _INET用于指定IPv4地址族

提示.ai_socktype=SOCK_STREAM; //SOCK _STREAM 用于指定流套接字

提示.ai_protocol=IPPROTO_TCP; //IPPROTO _TCP 用于指定tcp协议

提示.ai_flags=AI_PASSIVE;

//从本机获取IP地址等信息供sockce使用

iResult=getaddrinfo(NULL, DEFAULT_PORT, 提示, 结果);

if (iResult !=0) {

printf("getaddrinfo failed: %dn", iResult);

WSACleanup();

返回1;

}

//创建套接字对象

SOCKET ListenSocket=INVALID_SOCKET;

ListenSocket=套接字(结果-ai_family, 结果-ai_socktype, 结果-ai_protocol);

如果(ListenSocket==INVALID_SOCKET){

printf("socket(): %ldn 出错", WSAGetLastError());

freeaddrinfo(结果);

WSACleanup();

返回1;

}

//2.创建socket端

//3. 绑定套接字启动

iResult=bind(ListenSocket, 结果-ai_addr, (int)结果-ai_addrlen);

如果(iResult==SOCKET_ERROR){

printf("绑定失败,错误: %dn", WSAGetLastError());

freeaddrinfo(result);//调用bind函数后,不再需要地址信息。发布

关闭套接字(ListenSocket);

WSA清理

(); return 1; } // 3. 绑定套接字 end // 4.在套接字上监听客户端 start if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) { // SOMAXCONN定义了此套接字允许最大连接 printf("Listen failed with error: %ldn", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } // 4.在套接字上监听客户端 end // 5.接受来自客户端的连接 start SOCKET ClientSocket; //临时 套接字 对象,以接受来自客户端的连接 // 这里没有考虑多线程并发接受多个客户端 只接受一个 ClientSocket = accept(ListenSocket, NULL, NULL); if (ClientSocket == INVALID_SOCKET) { printf("accept failed: %dn", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } // 5.接受来自客户端的连接 end // 6.在服务器上接收和发送数据 start #define DEFAULT_BUFLEN 512 // 字符缓冲区长度 char recvbuf[DEFAULT_BUFLEN]; // 字符缓冲区数组 int iSendResult; int recvbuflen = DEFAULT_BUFLEN; do { iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); if (iResult >0) { printf("Bytes received: %dn", iResult); // recvbuf参数表示: 这里为了简单将客户端发送过来的消息再发送给客户端 iSendResult = send(ClientSocket, recvbuf, iResult, 0); if (iSendResult == SOCKET_ERROR) { printf("send failed: %dn", WSAGetLastError()); closesocket(ClientSocket); WSACleanup(); return 1; } printf("Bytes sent: %dn", iSendResult); } else if (iResult == 0) printf("Connection closing...n"); else { printf("recv failed: %dn", WSAGetLastError()); closesocket(ClientSocket); WSACleanup(); return 1; } } while (iResult >0); // 6.在服务器上接收和发送数据 end return 0; }备注: 这一步相当于完成了服务器的书写,但为了保险, 还是要关闭连接

7.断开连接

#include#include#include#pragma comment(lib, "Ws2_32.lib") int main() { // 1. 初始化 start WSADATA wsaData; int iResult; iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %dn", iResult); return 1; } // 1. 初始化 end // 2. 创建套接字 start #define DEFAULT_PORT "9501" // 服务器监听的端口 struct addrinfo* result = NULL, * ptr = NULL, hints; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; //AF _INET 用于指定 IPv4 地址族 hints.ai_socktype = SOCK_STREAM;// SOCK _STREAM 用于指定流套接字 hints.ai_protocol = IPPROTO_TCP;// IPPROTO _TCP 用于指定 tcp 协议 hints.ai_flags = AI_PASSIVE; // 从本机中获取ip地址等信息为了sockcet 使用 iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); if (iResult != 0) { printf("getaddrinfo failed: %dn", iResult); WSACleanup(); return 1; } // 创建socket对象 SOCKET ListenSocket = INVALID_SOCKET; ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ListenSocket == INVALID_SOCKET) { printf("Error at socket(): %ldn", WSAGetLastError()); freeaddrinfo(result); WSACleanup(); return 1; } // 2. 创建套接字 end // 3. 绑定套接字 start iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen); if (iResult == SOCKET_ERROR) { printf("bind failed with error: %dn", WSAGetLastError()); freeaddrinfo(result);// 调用 bind 函数后,不再需要地址信息 释放 closesocket(ListenSocket); WSACleanup(); return 1; } // 3. 绑定套接字 end // 4.在套接字上监听客户端 start if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) { // SOMAXCONN定义了此套接字允许最大连接 printf("Listen failed with error: %ldn", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } // 4.在套接字上监听客户端 end // 5.接受来自客户端的连接 start SOCKET ClientSocket; //临时 套接字 对象,以接受来自客户端的连接 // 这里没有考虑多线程并发接受多个客户端 只接受一个 ClientSocket = accept(ListenSocket, NULL, NULL); if (ClientSocket == INVALID_SOCKET) { printf("accept failed: %dn", WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; } // 5.接受来自客户端的连接 end // 6.在服务器上接收和发送数据 start #define DEFAULT_BUFLEN 512 // 字符缓冲区长度 char recvbuf[DEFAULT_BUFLEN]; // 字符缓冲区数组 int iSendResult; int recvbuflen = DEFAULT_BUFLEN; do { iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); if (iResult >0) { printf("Bytes received: %dn", iResult); // recvbuf参数表示: 这里为了简单将客户端发送过来的消息再发送给客户端 iSendResult = send(ClientSocket, recvbuf, iResult, 0); if (iSendResult == SOCKET_ERROR) { printf("send failed: %dn", WSAGetLastError()); closesocket(ClientSocket); WSACleanup(); return 1; } printf("Bytes sent: %dn", iSendResult); } else if (iResult == 0) printf("Connection closing...n"); else { printf("recv failed: %dn", WSAGetLastError()); closesocket(ClientSocket); WSACleanup(); return 1; } } while (iResult >0); // 6.在服务器上接收和发送数据 end // 7.断开连接 start iResult = shutdown(ClientSocket, SD_SEND); if (iResult == SOCKET_ERROR) { printf("shutdown failed: %dn", WSAGetLastError()); closesocket(ClientSocket); WSACleanup(); return 1; } // 7.断开连接 end return 0; }备注: 这里没有写控制台输入判断 进行关闭服务器 而是等客户端传输完数据后自动执行关闭逻辑

1.初始化

这一步和服务端一样, 见最上面

2.客户端创建套接字

需要重新用vs创建一个新项目当做客户端 #include#include#include#pragma comment(lib, "Ws2_32.lib") int main() { printf("启动客户端"); // 1. 初始化 start WSADATA wsaData; int iResult; iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %dn", iResult); return 1; } // 1. 初始化 end // 2. 创建套接字 start #define DEFAULT_IP "127.0.0.1"// 服务器为本机 #define DEFAULT_PORT "9501" // 服务器监听的端口 struct addrinfo* result = NULL, * ptr = NULL, hints; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; //AF _INET 用于指定 IPv4 地址族 hints.ai_socktype = SOCK_STREAM;// SOCK _STREAM 用于指定流套接字 hints.ai_protocol = IPPROTO_TCP;// IPPROTO _TCP 用于指定 tcp 协议 hints.ai_flags = AI_PASSIVE; // 从本机中获取ip地址等信息为了sockcet 使用 iResult = getaddrinfo(DEFAULT_IP, DEFAULT_PORT, &hints, &result); if (iResult != 0) { printf("getaddrinfo failed: %dn", iResult); WSACleanup(); return 1; } SOCKET ConnectSocket = INVALID_SOCKET; ConnectSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ConnectSocket == INVALID_SOCKET) { printf("Error at socket(): %ldn", WSAGetLastError()); freeaddrinfo(result); WSACleanup(); return 1; } // 2. 创建套接字 end return 0; }

3.客户端连接到该服务器

#include#include#include#pragma comment(lib, "Ws2_32.lib") int main() { printf("启动客户端"); // 1. 初始化 start WSADATA wsaData; int iResult; iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %dn", iResult); return 1; } // 1. 初始化 end // 2. 创建套接字 start #define DEFAULT_IP "127.0.0.1"// 服务器为本机 #define DEFAULT_PORT "9501" // 服务器监听的端口 struct addrinfo* result = NULL, * ptr = NULL, hints; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; //AF _INET 用于指定 IPv4 地址族 hints.ai_socktype = SOCK_STREAM;// SOCK _STREAM 用于指定流套接字

hints.ai_protocol = IPPROTO_TCP;// IPPROTO _TCP 用于指定 tcp 协议 hints.ai_flags = AI_PASSIVE; // 从本机中获取ip地址等信息为了sockcet 使用 iResult = getaddrinfo(DEFAULT_IP, DEFAULT_PORT, &hints, &result); if (iResult != 0) { printf("getaddrinfo failed: %dn", iResult); WSACleanup(); return 1; } SOCKET ConnectSocket = INVALID_SOCKET; ConnectSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ConnectSocket == INVALID_SOCKET) { printf("Error at socket(): %ldn", WSAGetLastError()); freeaddrinfo(result); WSACleanup(); return 1; } // 2. 创建套接字 end // 3. 连接到套接字 start for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if (ConnectSocket == INVALID_SOCKET) { printf("socket failed with error: %ldn", WSAGetLastError()); WSACleanup(); return 1; } iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); if (iResult == SOCKET_ERROR) { closesocket(ConnectSocket); ConnectSocket = INVALID_SOCKET; continue; } break; } // 3. 连接到套接字 end freeaddrinfo(result); return 0; }

4.客户端发送和接收数据

#include#include#include#pragma comment(lib, "Ws2_32.lib") int main() { printf("启动客户端"); // 1. 初始化 start WSADATA wsaData; int iResult; iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %dn", iResult); return 1; } // 1. 初始化 end // 2. 创建套接字 start #define DEFAULT_IP "127.0.0.1"// 服务器为本机 #define DEFAULT_PORT "9501" // 服务器监听的端口 struct addrinfo* result = NULL, * ptr = NULL, hints; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; //AF _INET 用于指定 IPv4 地址族 hints.ai_socktype = SOCK_STREAM;// SOCK _STREAM 用于指定流套接字 hints.ai_protocol = IPPROTO_TCP;// IPPROTO _TCP 用于指定 tcp 协议 hints.ai_flags = AI_PASSIVE; // 从本机中获取ip地址等信息为了sockcet 使用 iResult = getaddrinfo(DEFAULT_IP, DEFAULT_PORT, &hints, &result); if (iResult != 0) { printf("getaddrinfo failed: %dn", iResult); WSACleanup(); return 1; } SOCKET ConnectSocket = INVALID_SOCKET; ConnectSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ConnectSocket == INVALID_SOCKET) { printf("Error at socket(): %ldn", WSAGetLastError()); freeaddrinfo(result); WSACleanup(); return 1; } // 2. 创建套接字 end // 3. 连接到套接字 start for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if (ConnectSocket == INVALID_SOCKET) { printf("socket failed with error: %ldn", WSAGetLastError()); WSACleanup(); return 1; } iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); if (iResult == SOCKET_ERROR) { closesocket(ConnectSocket); ConnectSocket = INVALID_SOCKET; continue; } break; } // 3. 连接到套接字 end freeaddrinfo(result); // 4.在客户端上发送和接收数据 start #define DEFAULT_BUFLEN 512 int recvbuflen = DEFAULT_BUFLEN; const char* sendbuf = "Hello World"; char recvbuf[DEFAULT_BUFLEN]; // 发送 iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0); if (iResult == SOCKET_ERROR) { printf("send failed: %dn", WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } printf("Bytes Sent: %ldn", iResult); // 关闭 iResult = shutdown(ConnectSocket, SD_SEND); if (iResult == SOCKET_ERROR) { printf("shutdown failed: %dn", WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } // 接收 do { iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); if (iResult >0) printf("Bytes received: %dn", iResult); else if (iResult == 0) printf("Connection closedn"); else printf("recv failed: %dn", WSAGetLastError()); } while (iResult >0); // 4.在客户端上发送和接收数据 end return 0; }

5.客户端断开连接

#include#include#include#pragma comment(lib, "Ws2_32.lib") int main() { printf("启动客户端"); // 1. 初始化 start WSADATA wsaData; int iResult; iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %dn", iResult); return 1; } // 1. 初始化 end // 2. 创建套接字 start #define DEFAULT_IP "127.0.0.1"// 服务器为本机 #define DEFAULT_PORT "9501" // 服务器监听的端口 struct addrinfo* result = NULL, * ptr = NULL, hints; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; //AF _INET 用于指定 IPv4 地址族 hints.ai_socktype = SOCK_STREAM;// SOCK _STREAM 用于指定流套接字 hints.ai_protocol = IPPROTO_TCP;// IPPROTO _TCP 用于指定 tcp 协议 hints.ai_flags = AI_PASSIVE; // 从本机中获取ip地址等信息为了sockcet 使用 iResult = getaddrinfo(DEFAULT_IP, DEFAULT_PORT, &hints, &result); if (iResult != 0) { printf("getaddrinfo failed: %dn", iResult); WSACleanup(); return 1; } SOCKET ConnectSocket = INVALID_SOCKET; ConnectSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ConnectSocket == INVALID_SOCKET) { printf("Error at socket(): %ldn", WSAGetLastError()); freeaddrinfo(result); WSACleanup(); return 1; } // 2. 创建套接字 end // 3. 连接到套接字 start for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if (ConnectSocket == INVALID_SOCKET) { printf("socket failed with error: %ldn", WSAGetLastError()); WSACleanup(); return 1; } iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); if (iResult == SOCKET_ERROR) { closesocket(ConnectSocket); ConnectSocket = INVALID_SOCKET; continue; } break; } // 3. 连接到套接字 end freeaddrinfo(result); // 4.在客户端上发送和接收数据 start #define DEFAULT_BUFLEN 512 int recvbuflen = DEFAULT_BUFLEN; const char* sendbuf = "Hello World"; char recvbuf[DEFAULT_BUFLEN]; // 发送 iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0); if (iResult == SOCKET_ERROR) { printf("send failed: %dn", WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } printf("Bytes Sent: %ldn", iResult); // 关闭 iResult = shutdown(ConnectSocket, SD_SEND); if (iResult == SOCKET_ERROR) { printf("shutdown failed: %dn", WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } // 接收 do { iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); if (iResult >0) printf("Bytes received: %dn", iResult); else if (iResult == 0) printf("Connection closedn"); else printf("recv failed: %dn", WSAGetLastError()); } while (iResult >0); // 4.在客户端上发送和接收数据 end // 5.断开连接 start // 这里和服务器断开连接写在最后不同, 客户端断开连接写在 发送后 和 接收前 // shutdown(ConnectSocket, SD_SEND) SD_SEND表示socket的发送数据端虽然关闭(为了服务器释放客户端连接资源), 但是仍然能接收服务端的数据 //iResult = shutdown(ClientSocket, SD_SEND); //if (iResult == SOCKET_ERROR) { // printf("shutdown failed: %dn", WSAGetLastError()); // closesocket(ClientSocket); // WSACleanup(); // return 1; //} closesocket(ConnectSocket); WSACleanup(); // 5.断开连接 end return 0; }

结果

启动服务端 和客户端 可以看到, 双方都能接收到

文章分享结束,C++网络编程:Winsock2.h环境下Socket套接字应用教程和的答案你都知道了吗?欢迎再次光临本站哦!

用户评论

疲倦了

想学习一下网络编程,这篇文章挺合适的,终于找到C++Socket入门资料了!

    有13位网友表示赞同!

七夏i

Winsock2真是老可靠了,稳定性好,很多开源软件都用它实现网络通信。

    有18位网友表示赞同!

箜篌引

这个框架学习起来会比较复杂吗?需要先了解一些网络协议的概念吗?

    有20位网友表示赞同!

烟花巷陌

感觉看标题就很有难度,要看看文章里能提供哪些实际的例子,这样更容易理解。

    有15位网友表示赞同!

轨迹!

现在C++越来越常用在高性能网络应用中,学会Socket编程确实很有实用价值。

    有12位网友表示赞同!

千城暮雪

写这篇文档的人把内容讲解得清晰吗?有没有什么其他的学习资源可以参考?

    有12位网友表示赞同!

致命伤

不知道学习winsock2.h 这方面需要多少时间?希望这篇文章能提供一些参考。

    有12位网友表示赞同!

来瓶年的冰泉

Socket编程的原理还是不错的,可以实现各种不同类型的网络应用,从聊天工具到游戏服务器都有。

    有14位网友表示赞同!

凝残月

现在网络基础设施越来越复杂, Socket编程也是很重要的技能之一了。

    有7位网友表示赞同!

箜明

期待看到篇文章里能给出一些实际的代码例子,方便跟着实践练习理解。

    有9位网友表示赞同!

雨后彩虹

WINsock2.h这个头文件应该和Windows系统有关吧?

    有20位网友表示赞同!

情深至命

C++ 和网络编程结合起来真的很强大,可以实现许多很有趣的功能。

    有17位网友表示赞同!

白恍

这篇文章适合什么级别的开发者?新手也能看懂吗?

    有12位网友表示赞同!

夏以乔木

看完这篇文档,我希望能自己写一个简单的聊天程序试试,看看实际效果!

    有17位网友表示赞同!

长裙绿衣

网络编程真是个有趣的话题,希望能够深入学习了解。

    有8位网友表示赞同!

百合的盛世恋

有没有哪些好的教材或者教程可以配合这个文章一起学习?

    有5位网友表示赞同!

限量版女汉子

如果想要从事网络开发领域,这方面的知识是必不可少的。

    有11位网友表示赞同!

龙吟凤

C++ Socket编程的应用场景很多,除了聊天和游戏外还有哪些呢?

    有9位网友表示赞同!

逾期不候

看了标题就感觉很有挑战性了,我要努力学习一下!

    有13位网友表示赞同!

【C++网络编程:Winsock2.h环境下Socket套接字应用教程】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活

上一篇:每日Android面试题精选(第34天:热门Android学习网站推荐) 下一篇:精选语句:那些让我心动的瞬间