欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

收发文件的服务器端/客户端实现

程序员文章站 2022-03-04 22:20:34
...

程序需求

  1. 客户端接受用户输入的传输文件名
  2. 客户端请求服务器端传输该文件名所指文件

服务器端代码:

#include <iostream>
#include <string>
 
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
 
const int bufSize = 1024;
 
void error_handling(const std::string &message);
 
int main(int argc, char *argv[])
{
    int serv_sock, clnt_sock;
    char buffer[bufSize];
    int str_len, i;
 
    struct sockaddr_in serv_addr, clnt_addr;
    socklen_t clnt_addr_sz;
 
    if(argc != 2) {
        std::cout << "Usage : " << argv[0] << " <port>" << std::endl;
        exit(1);
    }
 
    serv_sock = socket(PF_INET, SOCK_STREAM, 0);
    if(serv_sock == -1)
        error_handling("socket() error");
 
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(atoi(argv[1]));
 
    if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
        error_handling("bind() error");
 
    if(listen(serv_sock, 1) == -1)
        error_handling("listen() error");
 
    clnt_addr_sz = sizeof(clnt_addr);
 
    for(size_t cnt = 0; true; ++cnt) {
        // get client socket
        clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_sz);
        if(clnt_sock == -1)
            error_handling("accept() error");
        std::cout << "Client connected, seq:" << cnt << std::endl;
 
        // get the filename
        memset(buffer, 0, bufSize);
        if((recv(clnt_sock, buffer, bufSize, 0)) < 0) {
            error_handling("failed to filename data!");
            break;
        }
 
        // start transmission
        std::string filename(buffer);
        FILE *fp = fopen(filename.c_str(), "r");
        if(fp == NULL) 
            std::cout << "NO_SUCH_FILE_REQUEST" << std::endl;
        else {
            memset(buffer, 0, bufSize);
            int sd_sz;  // size of data to send
            while((sd_sz = fread(buffer, 1, bufSize, fp)) > 0) {
                if(send(clnt_sock, buffer, sd_sz, 0) < 0) {  // see if failed
                    std::cout << "SEND_FILD_FAILED" << std::endl;
                    break;
                }
                memset(buffer, 0, bufSize);           
            }
            fclose(fp);
        }
 
        close(clnt_sock);
        std::cout << "clnt_sock closed (seq:" << cnt << ")" << std::endl;
    }
 
    close(serv_sock);
    return 0;
}
 
void error_handling(const std::string &message) {
    std::cerr << message << std::endl;
    exit(1);
}

客户端代码:

#include <iostream>
#include <string>
#include <regex>
 
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
 
const int bufSize = 1024;
void error_handling(const std::string &message);
int filename_check(const std::string &filename);
 
int main(int argc, char *argv[]) {
    int sock;
    char buffer[bufSize];
    std::string str_msg;
    int str_len;
    struct sockaddr_in serv_addr;
 
    if(argc != 3) {
        std::cout << "usage : " << argv[0] << " <IP> <port>" << std::endl;
        exit(1);
    }
    
    sock = socket(PF_INET, SOCK_STREAM, 0);
    if(sock == -1)
        error_handling("socket() error");
 
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
    serv_addr.sin_port = htons(atoi(argv[2]));
 
    if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
        error_handling("connect() error!");
    std::cout << "Connected......" << std::endl;
    std::cout << "Use 'quit' to finish the download" << std::endl;
 
    // get filename
    std::cout << "Input filename: " << std::ends;
    getline(std::cin, str_msg);
    // ATTENTION: these check should have been implemented in the server
    if(filename_check(str_msg) != 0)
        return 0;
 
    // check 
    FILE *fp = fopen(str_msg.c_str(), "w");
    if (fp == NULL)
        error_handling("Can't open/create the file!");
 
    if((send(sock, str_msg.c_str(),  str_msg.length(), 0)) < 0)
        error_handling("Send filename failed");
    std::cout << "filename sent..." << std::endl;
 
    int recv_sz;
    while( (recv_sz = recv(sock, buffer, bufSize-1, 0)) > 0 ) {    // receive the data
        if(fwrite(buffer, recv_sz, 1, fp) < 0) {    // write to a file
            std::cout << "Failed to write the file!" << std::endl;
            break;
        }
        memset(buffer, 0, bufSize);
    }
    std::cout << "Download finished..." << std::endl;
    fclose(fp);
    close(sock);
    return 0;
}
 
void error_handling(const std::string &message) {
    std::cerr << message << std::endl;
    exit(1);
}
 
int filename_check(const std::string &filename) {
    // check quit
    if(std::regex_match(filename, std::regex("[Qq]uit"))) {
        std::cout << "Client closed....." << std::endl;
        return 1;
    }
    // check illegal filename
    if(std::regex_match(filename, std::regex(".*(([\\.]{2})|([/])).*"))) {
        std::cout << "illegal filename!" << std::endl;
        return 2;
    }
    return 0;
}

 

相关标签: tcp/ip