C++ Windows Socket 文件传输服务器
#include <tchar.h>
#include <winsock2.h>
#include <string.h>
#include <Ws2tcpip.h>
#include
#define BUFFER_SIZE 2048 // 定义文件缓冲区大小 #define FILE_NAME_MAX_SIZE 512 // 定义文件名最大长度
using namespace std; string home = 'server_home/'; // 定义服务器存储文件的默认路径
string receiveData(SOCKET client_socket) { char buffer[BUFFER_SIZE]; memset(buffer, 0, BUFFER_SIZE); if (recv(client_socket, buffer, BUFFER_SIZE, 0) < 0) { perror('错误信息:接收客户端数据失败:\n'); return ''; } return buffer; }
bool sendData(SOCKET client_socket, const string& data) { if (send(client_socket, data.c_str(), data.length(), 0) < 0) { perror('错误信息:发送数据失败:\n'); return false; } return true; }
void uploadFile(SOCKET client_socket) { // 接收文件名 string file_name = receiveData(client_socket); if (file_name.empty()) { return; }
// 接收状态码
string stateNum = receiveData(client_socket);
if (stateNum.empty()) {
return;
}
if (stateNum == '1') {
cout << '错误信息:客户端未找到该文件名!\n' << endl;
return;
}
if (!sendData(client_socket, '1')) {
return;
}
// 准备写入文件
string file_path = home + file_name;
FILE* fp;
if (fopen_s(&fp, file_path.c_str(), 'wb') != 0)
{
cout << '文件打开失败!\n' << endl;
return;
}
// 从服务器接收数据到buffer中
// 每接收一段数据,便将其写入文件中,循环直到文件接收完并写完为止
cout << '接收文件中...\n' << endl;
char buffer[BUFFER_SIZE];
memset(buffer, 0, BUFFER_SIZE);
int length = 0;
while ((length = recv(client_socket, buffer, BUFFER_SIZE, 0)) > 0)
{
if (fwrite(buffer, sizeof(char), length, fp) < length)
{
cout << '文件写入失败!\n' << endl;
break;
}
memset(buffer, 0, BUFFER_SIZE);
}
cout << '文件接收成功!\n' << endl;
fclose(fp);
}
void downloadFile(SOCKET client_socket) { // 接收文件名 string file_name = receiveData(client_socket); if (file_name.empty()) { return; }
// 开始读取文件
string file_path = home + file_name;
FILE* fp;
if (fopen_s(&fp, file_path.c_str(), 'rb') != 0)
{
cout << '错误信息:未能找到该文件!\n' << endl;
sendData(client_socket, '1');
return;
}
else
{
sendData(client_socket, '2');
}
cout << '服务端开始传输文件!\n' << endl;
char buffer[BUFFER_SIZE];
memset(buffer, 0, BUFFER_SIZE);
int length = 0;
// 每读取一段数据,便将其发送给客户端,循环直到文件读完为止
while ((length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)
{
if (send(client_socket, buffer, length, 0) < 0)
{
cout << '错误信息:文件传输失败!\n' << endl;
break;
}
memset(buffer, 0, BUFFER_SIZE);
}
// 关闭文件
fclose(fp);
cout << '文件传输成功!\n' << endl;
}
void listFiles(SOCKET client_socket) { string path = 'C:\Users\72797\source\repos\计算机网络\Debug\server_home\'; //文件句柄 long hFile = 0; //文件信息 struct _finddata_t fileinfo; string p; if ((hFile = _findfirst(p.assign(path).append('*').c_str(), &fileinfo)) != -1) { do { p.assign(fileinfo.name); if (p == '.' || p == '..') continue; // 除本地目录和上级目录,排除
if (!sendData(client_socket, p)) {
break;
}
} while (_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
}
}
int main(int argc, char* argv[]) { // 初始化WSA,使得程序可以调用windows socket WORD sockVersion = MAKEWORD(2, 2); WSADATA wsaData; if (WSAStartup(sockVersion, &wsaData) != 0) { return 0; }
// 创建监听用套接字,server_socket,类型是TCP,并检测是否创建成功
SOCKET server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket == INVALID_SOCKET) {
perror('socket error !\n');
return 0;
}
// 创建地址,server_addr,并设置端口和IP
sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
//端口号 8888
server_addr.sin_port = htons(8888);
//INADDR_ANY表示本机任意IP地址
server_addr.sin_addr.S_un.S_addr = INADDR_ANY;
//将socket与地址server_addr绑定
if (bind(server_socket, (LPSOCKADDR)&server_addr, sizeof(server_addr)) == SOCKET_ERROR)
{
perror('bind error !\n');
return 0;
}
//server_socket开始监听
if (listen(server_socket, 20) == SOCKET_ERROR)
{
perror('listen error !\n');
return 0;
}
while (1)
{
cout << '等待连接...\n' << endl;
// 定义客户端的socket和socket地址结构
SOCKET client_socket;
sockaddr_in client_addr;
int client_addr_length = sizeof(client_addr);
// 接受连接请求,返回一个新的socket(描述符),这个新socket用于同连接的客户端通信
// accept函数会把连接到的客户端信息写到client_addr中
client_socket = accept(server_socket, (SOCKADDR*)&client_addr, &client_addr_length);
if (client_socket == INVALID_SOCKET)
{
perror('Socket连接建立失败:\n');
continue;
}
WCHAR IP_BUFFER[256] = TEXT('0');
InetNtop(AF_INET, &client_addr.sin_addr, IP_BUFFER, 256);
wcout << 'Socket连接建立,客户端IP为' << IP_BUFFER << ',端口为:\n'
<< ntohs(client_addr.sin_port) << endl;; // 宽字符记得用宽字符的方式进行输出
// 接受客户端请求的指令
string choice = receiveData(client_socket);
if (choice.empty()) {
break;
}
// 客户端选择上传文件
if (choice == '1')
{
uploadFile(client_socket);
}
// 客户端选择下载文件
else if (choice == '2')
{
downloadFile(client_socket);
}
// 客户端选择查看文件列表
else if (choice == '3')
{
listFiles(client_socket);
}
// 关闭与客户端的连接
closesocket(client_socket);
}
// 关闭监听用的socket
closesocket(server_socket);
WSACleanup();
return 0;
原文地址: https://www.cveoy.top/t/topic/pF0X 著作权归作者所有。请勿转载和采集!