解决方案: 先发送包长度,再发送包大小
server.cpp
#include <QCoreApplication>
#include <winsock.h>
#include <windows.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
DWORD WINAPI ThreadFun(LPVOID lpThreadParameter);
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//1.加载库
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
else
printf("The ServerWinsock 2.2 dll was found okay\n");
//2.创建socket
SOCKET sock = socket(AF_INET,SOCK_STREAM,0);
if (sock == INVALID_SOCKET)
{
WSACleanup();
return 1;
}
//3.绑定
sockaddr_in addrserver;
addrserver.sin_family = AF_INET;
addrserver.sin_port = htons(8899);
addrserver.sin_addr.S_un.S_addr=0;
if (SOCKET_ERROR == bind(sock,(const sockaddr*)&addrserver,sizeof(addrserver)))
{
closesocket(sock);
WSACleanup();
return 1;
}
//4.监听事件
//listen只是把套接字从主动变为被动,并限制链接数
if (SOCKET_ERROR == listen(sock,10))//10:服务器进程不能随便指定一个数值,内核有许可的范围
{
closesocket(sock);
WSACleanup();
return 1;
}
//5.拉着客人进店 ,将客人交给服务员
//SOCKET sockWaiter = accept(sock,0,0);//第一个参数指定处于监听状态的流套接字 第二个参数来返回新创建的套接字的地址结构 第三个参数来返回新创建套接字的地址结构的长度。
while(1)
{
sockaddr_in addrclient;
int len = sizeof (addrclient);
//接收成功返回与client通讯的socket //阻塞
SOCKET sockWaiter = accept(sock,(sockaddr*)&addrclient,&len);
if (sockWaiter != INVALID_SOCKET)
{
//创建线程 并且传入与client通讯的套接字
HANDLE hThread =CreateThread(0,0, &ThreadFun,(LPVOID)sockWaiter,0,0);
CloseHandle(hThread);
}
}
closesocket(sock);
WSACleanup();
return a.exec();
}
//线程通讯部分
DWORD WINAPI ThreadFun(LPVOID lpThreadParameter)
{
SOCKET sockWaiter = (SOCKET)lpThreadParameter;
while(1){
//6.接收消息 -- recv();
/*
* s<r normal;
* s>r 分次接
*/
char *pszbuf = NULL;//定义指针
int nRecNum;
int nPacksize;
int noffset;//偏移量
while(1)
{
noffset = 0;
//1.接收包大小 nRecNum代表接收的字节 例如:szbuf[100] 包大小100占用4个字节
nRecNum = recv(sockWaiter,(char*)&nPacksize,sizeof(int),0);
if (nRecNum <= 0) continue;
//2.包内容
pszbuf = new char[nPacksize];//创建nPacksize大小的空间
while(nPacksize) //当分次接收的包大小为0时,结束循环
{
nRecNum = recv(sockWaiter,pszbuf+noffset,nPacksize,0);
noffset += nRecNum;
nPacksize -= nRecNum;
}
cout<<pszbuf<<endl;
}
}
}
client.cpp
#include <QCoreApplication>
#include <winsock.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//加载库
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
else
printf("The ClientWinsock 2.2 dll was found okay\n");
//创建socket
SOCKET sock = socket(AF_INET,SOCK_STREAM,0);
if (sock == INVALID_SOCKET)
{
WSACleanup();
return 1;
}
//链接
sockaddr_in addrserver;
addrserver.sin_family = AF_INET;
addrserver.sin_port = htons(8899);
//inet_pton(AF_INET, "127.0.0.1", &addrserver.sin_addr);
addrserver.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
if (SOCKET_ERROR == connect(sock,(const sockaddr*)&addrserver,sizeof (addrserver)))
{
closesocket(sock);
WSACleanup();
return 1;
}
while(1){
char szbuf[1024] = {0};
cin>>szbuf;
//发送
//1.发送包长度
int nPackSize = sizeof(szbuf);
send(sock,(const char*)&nPackSize,sizeof(int),0);//发送一块缓冲区,所以第二个参数就是(const char*)&nPackSize 第三个参数:代表第二个参数的大小 第二个参数是int类型,所以是sizeof(int)
//2.发送包内容
send(sock,szbuf,sizeof(szbuf),0);
//接收
int RecvNum = recv(sock,szbuf,sizeof (szbuf),0);
if (RecvNum > 0)
{
cout<<szbuf<<endl;
}
}
//关闭socket
closesocket(sock);
//卸载库
WSACleanup();
return a.exec();
}