#include <tchar.h> #include <winsock2.h> #include <string.h> #include <Ws2tcpip.h> #include #include<io.h> #pragma comment(lib,'ws2_32.lib')

#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 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录