服务器
初始化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++网络编程:Winsock2.h环境下Socket套接字应用教程】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
想学习一下网络编程,这篇文章挺合适的,终于找到C++Socket入门资料了!
有13位网友表示赞同!
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位网友表示赞同!