socket局域网传输文件

使用socket局域网传输文件


server用于接收来自client发送的文件。server和client位于同一个局域网内就可以进行通信。

文件读写必须用二进制方式。

server端

有client连接时,开始接收数据,保存为文件。

#include <stdio.h>
#include <fstream>
#include <string>
#include <thread>

#include <winsock2.h>

#include <iostream>

using namespace std;
using std::ofstream;
using std::string;
using std::thread;

#pragma comment(lib, "ws2_32.lib")

const int bufsize = 1024; //缓冲大小 1024字节

int myrecv(SOCKET sockConn) // 收到客户端消息后保存文件
{
    char buffer[bufsize] = { 0 };
    // filename
    int ret = recv(sockConn, buffer, bufsize, 0);
    if (ret == -1) {
        std::cout << endl;
        return -1;
    }

#define _CPP
#ifdef _CPP
    string filename(buffer);
    cout << ", \"" << filename << "\"";

    // recvive file size
    recv(sockConn, buffer, bufsize, 0); 
    double count = atof(buffer); 
    cout << ", size = " << count/1024 << "Kb ";

    // recvive file content
    ofstream of(filename, ofstream::binary);
    memset(buffer, 0, bufsize);
    int sum = 0;
    while ((ret = recv(sockConn, buffer, bufsize, 0)) > 0)  // 反复接收二进制数据块
    {
        of.write(buffer, ret);
        sum += ret;
        memset(buffer, 0, bufsize);
        if (sum >= count)
            break;
    }
    of.close();

#else
    FILE * fd = fopen(buffer, "wb");
    memset(buffer, 0, bufsize);
    while ((ret = recv(sockConn, buffer, bufsize, 0)) > 0) {
        fwrite(buffer, 1, ret, fd);
        memset(buffer, 0, bufsize);
    }
    fclose(fd);
#endif

    cout << " Received done!" << endl;

    return 0;
}

int main(int argc, char * argv[]) {

    int port = 6000;// 默认端口6000

    if (argc == 2) {
        port = atoi(argv[1]);
    }

    WSADATA wsaData;
    int err;

    err = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (err != 0) {
        return -1;
        cerr << "ERROR: WSAStartup unsuccessful" << endl;
    }

    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        WSACleanup();
        return -1;
    }

    SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
    if (sockSrv == INVALID_SOCKET)
        cerr << "ERROR: socket unsuccessful" << endl;

    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(port);

    ///!!!!!!! 操蛋, 这里加::全局空间。。。否则客户端死活连接不上。。。
    err = ::bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(addrSrv));  
    if (err != 0) {
        return -1;
        cerr << "ERROR: bind unsuccessful" << endl;
    }

    err = listen(sockSrv, 5); // 监听
    if (err != 0) {
        return -1;
        cerr << "ERROR: listen unsuccessful" << endl;
    }

    //std::cout << "socket ptr: " << sockSrv << endl;

    SOCKADDR_IN addrClient;
    int len = sizeof(SOCKADDR);


    cout << "Wait for conneting..." << endl;
    while (true) {
        SOCKET sockConn = accept(sockSrv, (SOCKADDR *)&addrClient, &len);//有连接才返回

    //  cout << "\n==================================" << endl;
        cout << "Conneted by " << inet_ntoa(*((struct in_addr*)&addrClient.sin_addr)) << " ";

        thread t(myrecv, sockConn);
        t.join();
        /*myrecv(sockConn);*/
    }

    return 0;
}

client端

给定server端的ip和port,建立socket连接后发送文件。

#include <stdio.h>
#include <fstream>
#include <string>
//#include <thread>

#include <winsock2.h>

#include <iostream>

using namespace std;

#pragma comment(lib, "ws2_32.lib")

const int bufsize = 1024; //缓冲大小 1024字节


int myclient(int port, char * filename1, char * ip) 
{
    string tmp(filename1);
    int pos = tmp.rfind('\\');
    if (pos >= 0) {
        tmp = tmp.substr(pos + 1);   // 获取文件名称
    }

    cout << "file name: " << tmp << endl;

    char filename_buf[255] = { 0 };   // 文件名 用于发送
    strcpy(filename_buf, tmp.c_str());

    WSADATA wsaData;
    int err;

    err = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (err != 0)
        return -1;

    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        WSACleanup();
        return -1;
    }

    SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
    if (sockClient == INVALID_SOCKET)   {
        cerr << "ERROR: socket unsuccessful" << endl;
        WSACleanup();
        return -1;
    }

    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = inet_addr(ip);
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(port);

    //std::cout << "socket ptr: " << sockClient << endl;

    int ret = connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(addrSrv)); // 建立连接
    if(ret != 0 )
    {
        std::cout << "connet server failed: " << ret << endl;
        WSACleanup();
        return -1;
    }

    // send filename
    ret = send(sockClient, filename_buf, strlen(filename_buf) + 1, 0);
    if (ret == -1) {
        cerr << "send error" << endl;
        return -1;
    }

    // send content
#define _CPP
#ifdef _CPP
    string filename(filename1);
    ifstream fd(filename, ifstream::binary);
    fd.seekg(0, ifstream::end);

    // file size
    Sleep(100);
    char buf[bufsize] = { 0 };
    double filesize = fd.tellg();
    sprintf(buf, "%lf", filesize);

    send(sockClient, buf, strlen(buf), 0);  // send file size

    fd.seekg(0);
    memset(buf, 0, bufsize);
    Sleep(500);

    while (fd.good()) {
        fd.read(buf, bufsize);
        int count = fd.gcount();
        ret = send(sockClient, buf, count, 0);    // send content 
        if (ret == -1) {
            cerr << "error" << endl;
            return -1;
        }
        memset(buf, 0, bufsize);
    }
    fd.close();

#else
    FILE * fd = fopen(filename_buf, "rb");
    Sleep(500);
    char buf[bufsize] = { 0 };

    while (true) {
        int count = fread(buf, 1, bufsize, fd);
        if (count <= 0)
            break;

        ret = send(sockClient, buf, count, 0);
        if (ret == -1) {
            cerr << "error" << endl;
            return -1;
        }
        memset(buf, 0, bufsize);
    }
    fclose(fd);
#endif

    cout << "Send " << filename1 << " done." << endl;
    return 0;
}

int main(int argc, char * argv[])
{
    if (argc != 3)  {
        std::cout <<
            "command line: \n" <<
            "   client.exe file ip" << endl;
        return -1;
    }

    //argv[1] = R"(C:\Users\wanggao\Desktop\新建文本文档.txt)";
    //argv[2] = "192.168.3.113";

    int port = 6000;    // 与server相同
    char * filename;    // 文件
    char * server_ip;   // server地址

    filename = argv[1];
    server_ip = argv[2];

    return myclient(port, filename, server_ip);
}

猜你喜欢

转载自blog.csdn.net/wanggao_1990/article/details/80413004