很早写的了,感觉有点烂。
// server.cpp 服务器主要程序逻辑
#include <stdio.h>
#include <fstream>
#include <WinSock2.h>
#include <windows.h>
#include <ShareHeadFile.h>
#pragma comment(lib, "WS2_32.LIB")
static DWORD __stdcall ThreadFunc(LPVOID lpParam);
int main()
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 1), &wsaData) != 0)
{
printf("初始化WSADATA 失败!\n");
return 0;
}
// 1. 创建SOCKET
SOCKET sockServer = socket(AF_INET, SOCK_STREAM, 0);
if (sockServer == SOCKET_ERROR)
{
printf("创建SOCKET 失败!\n");
WSACleanup();
return 0;
}
// 2. 绑定服务器主机地址
sockaddr_in addrServer;
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(PORT);
addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
// 绑定
if (bind(sockServer, (sockaddr *)&addrServer, sizeof(addrServer)) == SOCKET_ERROR)
{
printf("绑定失败!\n");
closesocket(sockServer);
WSACleanup();
return 0;
}
// 3. 监听
listen(sockServer, 10);
// 4. 连接通信
while (1)
{
sockaddr_in addrClient;
int nLen = sizeof(addrClient);
SOCKET *pSockClient = new SOCKET;
*pSockClient = accept(sockServer, (sockaddr *)&addrClient, &nLen);
if (*pSockClient == SOCKET_ERROR)
{
printf("accept 失败!\n");
break;
}
printf("客户端: %s 连接上来!\n", inet_ntoa(addrClient.sin_addr));
CreateThread(NULL, 0, &ThreadFunc, pSockClient, 0, NULL);
}
closesocket(sockServer);
WSACleanup();
return 0;
}
// 线程函数
static DWORD __stdcall ThreadFunc(LPVOID lpParam)
{
if (lpParam == NULL)
return 0;
SOCKET sockClient = *((SOCKET *)lpParam);
delete (SOCKET *)lpParam, lpParam = NULL;
char strFile[4096] = {0};
recv(sockClient, strFile, 4096, 0);
std::ifstream readFile(strFile, std::ios::binary);
if (!readFile)
{
printf("打开文件: %s 失败!\n", strFile);
closesocket(sockClient);
return 0;
}
STRU_Package struPackage;
int nSendCount = 0;
int nDataPackageCount = 0;
while (1)
{
if (readFile.eof())
{
printf("文件全部发送完毕。\n");
break;
}
readFile.read(struPackage.arrData + 1, DATA_SIZE);
struPackage.arrData[0] = (readFile.eof() ? 1 : 0);
// 当前包中实际字节数
struPackage.lDataLength = htonl((unsigned long)readFile.gcount());
nDataPackageCount = (int)(sizeof(struPackage.lDataLength) + 1 + readFile.gcount());
nSendCount = send(sockClient, (const char *)&struPackage,
nDataPackageCount, 0);
if (nSendCount < 0)
{
printf("发送失败...\n");
break;
}
}
readFile.close();
closesocket(sockClient);
return 0;
}
// 客户端主要程序代码
#include <stdio.h>
#include <WinSock2.h>
#include <fstream>
#include <ShareHeadFile.h>
#include <io.h>
#pragma comment(lib, "WS2_32.LIB")
int main()
{
#ifdef WIN32
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 1), &wsaData) != 0)
{
printf("初始化WSADATA 失败!\n");
return -1;
}
#endif
// 1. 创建SOCKET
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
if (sockClient == SOCKET_ERROR)
{
printf("创建SOCKET 失败!\n");
WSACleanup();
return -2;
}
// 2. 准备服务器地址
//fflush(stdin);
char szServerIP[64] = {0};
printf("输入服务器地址: ");
scanf(" %s", szServerIP);
sockaddr_in addrServer;
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(PORT);
addrServer.sin_addr.S_un.S_addr = (inet_addr(szServerIP));
// 3. 连接到服务器
if (connect(sockClient, (const sockaddr *)&addrServer,
sizeof(addrServer)) != 0)
{
printf("连接到服务器失败!\n");
closesocket(sockClient);
WSACleanup();
return -3;
}
// 4. 与服务器通信
char strFile[MAX_PATH] = {0};
fflush(stdin);
printf("输入文件名:");
scanf(" %s", strFile);
send(sockClient, strFile, strlen(strFile) + 1, 0);
char *pCh = strrchr(strFile, '\\');
(pCh == NULL) ? (pCh = strFile) : (++pCh);
char strName[MAX_PATH] = "D:\\TestDir\\";
strcat(strName, pCh);
FILE *fp = fopen(strName, "wb");
if (fp == NULL)
{
closesocket(sockClient);
WSACleanup();
return -4;
}
printf("开始文件。\n");
STRU_Package struPackage;
char arrRecvBuff[sizeof(STRU_Package)] = {0};
unsigned long uIndex = 0;
while (1)
{
int nRecvCount = 0;
nRecvCount = recv(sockClient, arrRecvBuff + uIndex,
sizeof(arrRecvBuff) - uIndex, 0);
if (nRecvCount < 0)
{
printf("接收文件出错\n");
break;
}
uIndex += nRecvCount;
// 缓冲区中的数据连一个整数的个数都不到则需要继续recv
if (uIndex < sizeof(struPackage.lDataLength))
continue;
// 前4个字符为数据的字符个数
struPackage.lDataLength = ntohl(*((u_long *)arrRecvBuff));
if (uIndex < sizeof(struPackage.lDataLength) + sizeof(char)
+ struPackage.lDataLength )
continue;
// 将数据写入文件
size_t sizeWrite = 0;
sizeWrite = fwrite(
arrRecvBuff + (sizeof(struPackage.lDataLength) + sizeof(char)),
struPackage.lDataLength, 1, fp);
if (sizeWrite < 0)
printf("数据写入错误\n");
if (arrRecvBuff[sizeof(struPackage.lDataLength)])
{
printf("数据接收完成\n");
break;
}
// 移动数据到首部
int nUseSize = sizeof(struPackage.lDataLength) + sizeof(char) + struPackage.lDataLength;
int nUnUseSize = uIndex - nUseSize;
if (nUnUseSize > 0)
{
memmove(arrRecvBuff, arrRecvBuff + nUseSize, nUnUseSize);
uIndex = nUnUseSize;
}
else
uIndex = 0;
}
printf("文件接收完成。\n");
fclose(fp), fp = NULL;
closesocket(sockClient);
WSACleanup();
return 0;
}