ftp并发套接字编程

基于ftp的多线程Socket编程,服务器端和客户端可以互传文件。

编译环境:VS2019,VC++

先在D盘添加file_server和file_client文件夹,在里面可以新建一些文件,方便客户端上传与下载。

有注释,贴上源码,供大家学习参考。

服务器端 Server.cpp

#include <windows.h>
#include <stdio.h>
#include<iostream>
#include <string.h>
#pragma comment (lib,"ws2_32")
using namespace std;
#define BUF_SIZE 1024

void RecvFile(char name[], SOCKET s) {

    char FileName[MAXBYTE] = "";
    sprintf(FileName, "D:\file_server\%s", name);

    char info[BUF_SIZE];
    recv(s, info, BUF_SIZE, 0);
    cout << info << endl;

    if (!strcmp(info, "传输文件失败, 文件不存在!
")) {

    }
    else {
        DWORD dwWrite;
        HANDLE hFile = CreateFile(FileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
        char szBufferfile[BUF_SIZE] = { NULL };
        char ok[BUF_SIZE] = { NULL };

        while (true) {

            int read = recv(s, szBufferfile, BUF_SIZE, 0);
            if (!strcmp(ok, szBufferfile)) {
                printf("接收文件成功!!!
"); break;
            }
            bool bRet = WriteFile(hFile, szBufferfile, read, &dwWrite, NULL);
        }

        CloseHandle(hFile);
    }
    
}


void Sender(char name[], SOCKET clientSock) {

    char FileName[MAXBYTE] = "";
    sprintf(FileName, "D:\file_server\%s", name);

    char ok[BUF_SIZE] = { NULL };
    char SendBuf[BUF_SIZE] = { NULL };
    DWORD dwRead;
    HANDLE hFile = CreateFile(FileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if (hFile == INVALID_HANDLE_VALUE) {
        send(clientSock, "传输文件失败, 文件不存在!
", BUF_SIZE, 0);
    }
    else {
        send(clientSock, "开始接收文件
", BUF_SIZE, 0);
        while (TRUE) {
            bool bRet = ReadFile(hFile, SendBuf, BUF_SIZE, &dwRead, NULL);
            if (bRet == FALSE) {
                //MessageBox(NULL, "Read Buf ERROR!", "Error", MB_OK);
                CloseHandle(hFile);
                break;
            }
            else if (dwRead == 0)
            {
                //MessageBox(NULL, "Send file OK!", "OK", MB_OK);
                CloseHandle(hFile);
                printf("发送文件成功!!!
");
                send(clientSock, ok, BUF_SIZE, 0);
                break;
            }
            else
            {
                send(clientSock, SendBuf, BUF_SIZE, 0);
            }
        }
    }
}


DWORD WINAPI ClientThread(LPVOID IpParam) {
    SOCKET clientSock = (SOCKET)IpParam;
    printf("与客户端取得连接,套接字编号为%u
", clientSock);

    char RecvBuf[MAXBYTE];
    char FileName[MAXBYTE] = { NULL };
    int read = 0;
    char getcheck[6] = { "down" };
    char upcheck[6] = { "up" };

    while (true) {
        memset(RecvBuf, 0, MAXBYTE);//与客户端进行文字通信
        read = recv(clientSock, RecvBuf, MAXBYTE, 0);

        if (read == -1) break;

        printf(RecvBuf);
        printf("
");

        if (!strcmp(RecvBuf, getcheck)) {        // get 下载文件

            memset(FileName, 0, MAXBYTE);

            read = recv(clientSock, FileName, MAXBYTE, 0);
            if (read == -1) break;
            printf("%s
", FileName);
            Sender(FileName, clientSock);

        }
        else if (!strcmp(RecvBuf, upcheck)) {

            memset(FileName, 0, MAXBYTE);
            recv(clientSock, FileName, MAXBYTE, 0);
            RecvFile(FileName, clientSock);

        }
        else {
            send(clientSock, "无效的命令,请重新输入..
", MAXBYTE, NULL);
        }
    }

    closesocket(clientSock);
    return 0;
}

int main(int argc, char* argv[]) {
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);                                //套接字s用于监听

    sockaddr_in sockaddr;
    sockaddr.sin_family = PF_INET;
    sockaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    sockaddr.sin_port = htons(827);
    bind(s, (SOCKADDR*)&sockaddr, sizeof(sockaddr));                                     //绑定套接字 ip,端口号

    SOCKADDR clientAddr = { 0 };
    int nSize = sizeof(SOCKADDR);
    SOCKET clientSock;

    listen(s, 1);
    //循环接受客户端连接请求,并生成线程去处理:
    printf("I'm server
");
    while(1) {
        //等待接受客户端控制连接请求
        clientSock = accept(s, (SOCKADDR*)&clientAddr, &nSize);

        //创建一个线程来处理相应客户端的请求:
        DWORD dwThreadId, dwThrdParam = 1;
        HANDLE hThread;

        hThread = CreateThread(
            NULL,               //无需安全性的继承
            0,                    //默认线程栈大小
            ClientThread,            //线程入口函数
            (LPVOID)clientSock,            //线程入口函数的参数
            0,                    //立即启动线程
            &dwThreadId);        //返回线程的id值

        //检查返回值是否创建线程成功
        if (hThread == NULL) {
            printf("创建线程失败。
");
            closesocket(s);
        }

        CloseHandle(hThread);
    }
    
    closesocket(clientSock);
    closesocket(s);

    WSACleanup();

    return 0;
}

客户端 Client.cpp

#include<iostream>
#include<winsock2.h>
#pragma comment (lib,"ws2_32")
using namespace std;

#define BUF_SIZE 1024
void RecvFile(char name[], SOCKET s) {

    char FileName[MAXBYTE] = "";
    sprintf(FileName, "D:\file_client\%s", name);

    char info[BUF_SIZE];
    recv(s, info, BUF_SIZE, 0);
    cout << info << endl;

    if (!strcmp(info, "传输文件失败, 文件不存在!
")) {

    }
    else {
        DWORD dwWrite;
        HANDLE hFile = CreateFile(FileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
        char szBufferfile[BUF_SIZE] = { NULL };
        char ok[BUF_SIZE] = { NULL };

        while (true) {

            int read = recv(s, szBufferfile, BUF_SIZE, 0);
            if (!strcmp(ok, szBufferfile)) {
                printf("已接收到文件!!!
"); break;
            }
            bool bRet = WriteFile(hFile, szBufferfile, read, &dwWrite, NULL);
        }

        CloseHandle(hFile);
        printf("写入文件成功!!!
");
    }
}

void Sender(char name[], SOCKET clientSock) {

    char FileName[MAXBYTE] = "";
    sprintf(FileName, "D:\file_client\%s", name);

    char ok[BUF_SIZE] = { NULL };
    char SendBuf[BUF_SIZE] = { NULL };
    DWORD dwRead;
    HANDLE hFile = CreateFile(FileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if (hFile == INVALID_HANDLE_VALUE) {
        cout << "传输文件失败, 文件不存在!" << endl;
        send(clientSock, "传输文件失败, 文件不存在!
", BUF_SIZE, 0);
    }
    else {
        send(clientSock, "开始接收文件...
", BUF_SIZE, 0);
        while (TRUE) {
            bool bRet = ReadFile(hFile, SendBuf, BUF_SIZE, &dwRead, NULL);
            if (bRet == FALSE) {
                //MessageBox(NULL, "Read Buf ERROR!", "Error", MB_OK);
                CloseHandle(hFile);
                break;
            }
            else if (dwRead == 0)
            {
                //MessageBox(NULL, "Send file OK!", "OK", MB_OK);
                CloseHandle(hFile);
                printf("发送文件成功!!!
");
                send(clientSock, ok, BUF_SIZE, 0);
                break;
            }
            else
            {
                send(clientSock, SendBuf, BUF_SIZE, 0);
            }
        }
    }
}

int main(int argc, char* argv[])
{
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);                 //创建套接字

    sockaddr_in sockAddr;
    sockAddr.sin_family = PF_INET;
    sockAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    sockAddr.sin_port = htons(827);

    char SendBuf[MAXBYTE];
    char szBuffer[MAXBYTE] = { NULL };
    char FileName[MAXBYTE] = { NULL };
    char getcheck[6] = { "down" };
    char upcheck[6] = { "up" };
    char bye[6] = { "exit" };

    printf("I'm Client
1)down:从服务端下载文件
2)up:上传文件到服务器
3)exit:退出
");
    //cout << "Server:" << endl;
    connect(s, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));                     //给服务器端发送TCP链接请求

    while (TRUE) {
        cout << "Client:";
        memset(SendBuf, 0, MAXBYTE);
        cin >> SendBuf;

        if (!strcmp(SendBuf, getcheck)) {
            send(s, SendBuf, MAXBYTE, NULL);
            cout << "filename:";
            memset(FileName, 0, MAXBYTE);
    
            cin >> FileName;
            send(s, FileName, MAXBYTE, NULL);
            RecvFile(FileName, s);
            continue;
        }

        else if (!strcmp(SendBuf, upcheck)) {
            send(s, SendBuf, MAXBYTE, NULL);
            cout << "filename:";
            memset(FileName, 0, MAXBYTE);

            cin >> FileName;
            send(s, FileName, MAXBYTE, NULL);
            Sender(FileName, s);
            continue;
        }
        else if (!strcmp(SendBuf, bye)) {

            cout << "已退出。
" << endl;
            break;

        }
        send(s, SendBuf, MAXBYTE, NULL);
        memset(szBuffer, 0, MAXBYTE);
        memset(SendBuf, 0, MAXBYTE);
        recv(s, szBuffer, MAXBYTE, NULL);
        cout << szBuffer;
    }
    closesocket(s);
    WSACleanup();
    return 0;
}
原文地址:https://www.cnblogs.com/wqvincent/p/14691911.html