下面的代码演示了粘包问题,客户端连续三次向服务器端发送数据,服务器端却一次性接收到所有数据。
服务器代码
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <iostream>
using namespace std;
//#include <stdio.h>
#include <WinSock2.h>
//
#pragma comment(lib, "ws2_32.lib")
#define BUF_SIZE 100
int main(void)
{
// 1.初始化套接字库
WORD wVersion;
WSADATA wsaData;
int err;
// 设置版本,可以理解为1.1
wVersion = MAKEWORD(1, 1); // 例:MAKEWORD(a, b) --> b | a << 8 将a左移8位变成高位与b合并起来
// 启动
err = WSAStartup(wVersion, &wsaData);
if (err != 0)
{
return err;
}
// 检查:网络低位不等于1 || 网络高位不等于1
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
// 清理套接字库
WSACleanup();
return -1;
}
// 2.创建tcp套接字 // AF_INET:ipv4 AF_INET6:ipv6
SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
// 准备绑定信息
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 设置绑定网卡
addrSrv.sin_family = AF_INET; // 设置绑定网络模式
addrSrv.sin_port = htons(6000); // 设置绑定端口
// hton: host to network x86:小端 网络传输:htons大端
// 3.绑定到本机
int retVal = bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
if (retVal == SOCKET_ERROR)
{
cout << "Failed bind:%d\n"<< WSAGetLastError()<<endl;
return -1;
}
// 4.监听,同时能接收10个链接
if (listen(sockSrv, 10) == SOCKET_ERROR)
{
cout << "Listen failed:%d"<<WSAGetLastError()<<endl;
return -1;
}
cout << "Server start at port: 6000" << std::endl;
SOCKADDR_IN addrCli;
int len = sizeof(SOCKADDR);
// 5.接收连接请求,返回针对客户端的套接字
SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrCli, &len);
cout << "Accept client IP: " << inet_ntoa(addrCli.sin_addr) << std::endl;
if (sockConn == SOCKET_ERROR)
{
cout << "Accept failed: " << WSAGetLastError() << std::endl;
return -1;
}
char recvBuf[BUF_SIZE];
char sendBuf[BUF_SIZE];
// 7.接收数据
recv(sockConn, recvBuf, BUF_SIZE, 0);
cout << "客户端:" << recvBuf << std::endl;
// 8.关闭套接字
closesocket(sockSrv);
// 9.清理套接字库
WSACleanup();
return 0;
}
//#include <stdio.h>
//#include <windows.h>
//#pragma comment (lib, "ws2_32.lib") //加载 ws2_32.dll
//
//#define BUF_SIZE 100
//
//int main()
//{
// WSADATA wsaData;
// WSAStartup(MAKEWORD(2, 2), &wsaData);
//
// //创建套接字
// SOCKET servSock = socket(AF_INET, SOCK_STREAM, 0);
//
// //绑定套接字
// sockaddr_in sockAddr;
// memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都用0填充
// sockAddr.sin_family = PF_INET; //使用IPv4地址
// sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址
// sockAddr.sin_port = htons(1234); //端口
// bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
//
// //进入监听状态
// if(listen(servSock, 20) == SOCKET_ERROR)
// {
// cout << "Listen failed:%d" << WSAGetLastError() << endl;
// return -1;
// }
// cout << "Server start at port: 1234" << std::endl;
//
// //接收客户端请求
// SOCKADDR_IN clntAddr;
// int nSize = sizeof(SOCKADDR);
// char buffer[BUF_SIZE] = { 0 }; //缓冲区
// SOCKET clntSock = accept(servSock, (SOCKADDR*)&clntAddr, &nSize);
// cout << "Accept client IP: " << inet_ntoa(clntAddr.sin_addr) << std::endl;
// if (clntSock == SOCKET_ERROR)
// {
// cout << "Accept failed: " << WSAGetLastError() << std::endl;
// return -1;
// }
//
// Sleep(10000); //注意这里,让程序暂停10秒
//
// //接收客户端发来的数据,并原样返回
// int recvLen = recv(clntSock, buffer, BUF_SIZE, 0);
// printf("recv buffer: %s", buffer);
// send(clntSock, buffer, recvLen, 0);
//
// //关闭套接字并终止DLL的使用
// closesocket(clntSock);
// closesocket(servSock);
// WSACleanup();
//
// return 0;
//}
客户端代码
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <iostream>
using namespace std;
#include <WinSock2.h>
#include <stdio.h>
#include <string.h>
#pragma comment(lib, "ws2_32.lib")
#define BUF_SIZE 100
int main(void)
{
// 1.初始化套接字库
WORD wVersion;
WSADATA wsaData;
int err;
// 可以理解为1.1
wVersion = MAKEWORD(1, 1); // 例:MAKEWORD(a, b) --> b | a << 8 将a左移8位变成高位与b合并起来
// 启动
err = WSAStartup(wVersion, &wsaData);
if (err != 0)
{
return err;
}
// 检查:网络地位不等于1 || 网络高位不等于1
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
// 清理套接字库
WSACleanup();
return -1;
}
// 创建TCP套接字
SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // 服务器地址
addrSrv.sin_port = htons(6000); // 端口号
addrSrv.sin_family = AF_INET; // 地址类型(ipv4)
// 2.连接服务器
int err_log = connect(sockCli, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
if (err_log == 0)
{
cout << "连接服务器成功!" << endl;
}
else
{
cout << "连接服务器失败!" << endl;
return -1;
}
char recvBuf[BUF_SIZE];
char sendBuf1[BUF_SIZE] = "data1";
char sendBuf2[BUF_SIZE] = "data2";
char sendBuf3[BUF_SIZE] = "data3";
// 3.发送数据
send(sockCli, sendBuf1, strlen(sendBuf1), 0);
send(sockCli, sendBuf2, strlen(sendBuf2), 0);
send(sockCli, sendBuf3, strlen(sendBuf3), 0);
// 5.关闭套接字并清除套接字库
closesocket(sockCli);
WSACleanup();
system("pause");
return 0;
}
//#define BUF_SIZE 100
//
//int main()
//{
// //初始化DLL
// WSADATA wsaData;
// WSAStartup(MAKEWORD(2, 2), &wsaData);
//
// //向服务器发起请求
// sockaddr_in sockAddr;
// memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都用0填充
// sockAddr.sin_family = PF_INET;
// sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
// sockAddr.sin_port = htons(1234);
//
// //创建套接字
// SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
// connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
//
// //获取用户输入的字符串并发送给服务器
// char bufSend[BUF_SIZE] = { 0 };
// //printf("Input a string: ");
// //gets_s(bufSend);
// sprintf_s(bufSend, "你好!");
// for (int i = 0; i < 3; i++)
// {
// send(sock, bufSend, strlen(bufSend), 0);
// }
// //接收服务器传回的数据
// char bufRecv[BUF_SIZE] = { 0 };
// recv(sock, bufRecv, BUF_SIZE, 0);
// //输出接收到的数据
// printf("Message form server: %s\n", bufRecv);
//
// closesocket(sock); //关闭套接字
// WSACleanup(); //终止使用 DLL
//
// system("pause");
// return 0;
//}
执行结果:
标签:sockAddr,MAKEWORD,lib,int,C++,粘包,TCP,include,define From: https://www.cnblogs.com/zhuchunlin/p/18217567