使用socket tcp实现简单的文件传输

程序分为server、client两个部分,client从server获取文件。流程如下:

server:

1、创建socket,绑定端口10002,等待client连接;

2、链接后打开需要发送的文件,计算文件长度并发送长度,等待接收客户端响应;

3、客户端响应ok后,发送文件数据,发送缓冲定位8192;

4、发送结束后关闭链接;


client:

1、创建socket,链接server;

2、接收文件长度,并回复ok;

3、接收数据并写入文件,接收缓冲为8192;

4、接收结束后关闭链接;


参考代码如下:

file_server.c:

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>

#define BUF_SIZE  (8192)

unsigned char fileBuf[BUF_SIZE];

/*
 * send file
 */
void
file_server(const char *path)
{
    int skfd, cnfd;
    FILE *fp = NULL;
    struct sockaddr_in sockAddr, cltAddr;
    socklen_t addrLen;
    unsigned int fileSize;
    int size, netSize;
    char buf[10];

    if( !path ) {
        printf("file server: file path error!\n");
        return;
    }

    //创建tcp socket
    if((skfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket");
        exit(1);
    } else {
        printf("socket success!\n");
    }

    //创建结构  绑定地址端口号
    memset(&sockAddr, 0, sizeof(struct sockaddr_in));
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    sockAddr.sin_port = htons(10002);

    //bind
    if(bind(skfd, (struct sockaddr *)(&sockAddr), sizeof(struct sockaddr)) < 0) {
        perror("Bind");
        exit(1);
    } else {
        printf("bind success!\n");
    }

    //listen   监听  最大4个用户
    if(listen(skfd, 4) < 0) {
        perror("Listen");
        exit(1);
    } else {
        printf("listen success!\n");
    }

    /* 调用accept,服务器端一直阻塞,直到客户程序与其建立连接成功为止*/
    addrLen = sizeof(struct sockaddr_in);
    if((cnfd = accept(skfd, (struct sockaddr *)(&cltAddr), &addrLen)) < 0) {
        perror("Accept");
        exit(1);
    } else {
        printf("accept success!\n");
    }

    fp = fopen(path, "r");
    if( fp == NULL ) {
        perror("fopen");
        close(cnfd);
        close(skfd);
        return;
    }

    fseek(fp, 0, SEEK_END);
    fileSize = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    if(write(cnfd, (unsigned char *)&fileSize, 4) != 4) {
        perror("write");
        close(cnfd);
        close(skfd);
        exit(1);
    }

    if( read(cnfd, buf, 2) != 2) {
        perror("read");
        close(cnfd);
        close(skfd);
        exit(1);
    }

    while( ( size = fread(fileBuf, 1, BUF_SIZE, fp) ) > 0 ) {
        unsigned int size2 = 0;
        while( size2 < size ) {
            if( (netSize = write(cnfd, fileBuf + size2, size - size2) ) < 0 ) {
                perror("write");
                close(cnfd);
                close(skfd);
                exit(1);
            }
            size2 += netSize;
        }
    }

    fclose(fp);
    close(cnfd);
    close(skfd);
}

int
main(int argc, char **argv)
{
    if( argc < 2 ) {
        printf("file server: argument error!\n");
        printf("file_server /tmp/temp\n");
        return -1;
    }

    file_server(argv[1]);

    return 0;
}

file_client.c:

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>

#define BUF_SIZE (8192)

unsigned char fileBuf[BUF_SIZE];

void
file_client(const char *ip, const char *path)
{
    int skfd;
    FILE *fp = NULL;
    struct sockaddr_in sockAddr;
    unsigned int fileSize, fileSize2;
    int size, nodeSize;

    //创建tcp socket
    if((skfd=socket(AF_INET,SOCK_STREAM,0)) < 0) {
        perror("socket");
        exit(1);
    } else {
        printf("socket success!\n");
    }

    //创建结构设定待连接的服务器地址端口号
    memset(&sockAddr, 0, sizeof(struct sockaddr_in));
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_addr.s_addr = inet_addr(ip);
    sockAddr.sin_port = htons(10002);

    /* 客户端调用connect主动发起连接请求 */
    if(connect(skfd, (struct sockaddr *)(&sockAddr), sizeof(struct sockaddr)) < 0) {
        perror("ConnectError:");
        exit(1);
    } else {
        printf("connnect success!\n");
    }

    size = read(skfd, (unsigned char *)&fileSize, 4);
    if( size != 4 ) {
        printf("file size error!\n");
        close(skfd);
        exit(-1);
    }
    printf("file size:%d\n", fileSize);

    if( (size = write(skfd, "OK", 2) ) < 0 ) {
        perror("write");
        close(skfd);
        exit(1);
    }

    fp = fopen(path, "w");
    if( fp == NULL ) {
        perror("fopen");
        close(skfd);
        return;
    }

    fileSize2 = 0;
    while(memset(fileBuf, 0, sizeof(fileBuf)), (size = read(skfd, fileBuf, sizeof(fileBuf))) > 0) {
        unsigned int size2 = 0;
        while( size2 < size ) {
            if( (nodeSize = fwrite(fileBuf + size2, 1, size - size2, fp) ) < 0 ) {
                perror("write");
                close(skfd);
                exit(1);
            }
            size2 += nodeSize;
        }
        fileSize2 += size;
        if(fileSize2 >= fileSize) {
            break;
        }
    }
    fclose(fp);
    close(skfd);
}

int
main(int argc, char **argv)
{
    if( argc < 3 ) {
        printf("file client: argument error!\n");
        printf("file_client 192.168.1.10 /tmp/temp\n");
        return -1;
    }

    file_client(argv[1], argv[2]);

    return 0;
}

测试结果:

首先启动server端,发送文件mysql-server-8.0.zip

$ ~/tmp/test/fileserver mysql-server-8.0.zip

再启动client端,接收此文件

$ ./fileclient 10.9.0.132 ./mysql.zip

接收成功后解压这个文件测试传输是否成功。

















  • 23
    点赞
  • 191
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论
实现一个基于 TCP文件传输服务器,你可以按照以下步骤进行: 1. 创建一个 TCP 服务器端程序。你可以使用编程语言(如Python、Java、C++等)提供的网络编程库来实现。在服务器端程序中,你需要创建一个 TCP socket,并绑定到指定的 IP 地址和端口上。 2. 等待客户端的连接请求。使用 socket 的 listen() 函数开始监听来自客户端的连接请求。 3. 接受客户端连接。一旦有客户端发起连接请求,使用 socket 的 accept() 函数接受连接,并返回一个新的 socket 对象用于与客户端进行通信。 4. 接收文件请求。与客户端建立连接后,你可以定义一种协议来传输文件。例如,可以约定客户端发送一个特定的命令来请求文件传输。 5. 打开文件并读取内容。在服务器端,根据客户端请求的文件名,打开相应的文件,并读取文件内容。 6. 将文件内容发送给客户端。使用 socket 的 send() 函数将文件内容逐个数据包发送给客户端。你可以定义合适的数据包大小(如 1024 字节)来进行分包发送。 7. 客户端接收并保存文件内容。在客户端程序中,接收服务器发送的数据包,并将数据包逐个写入文件中,最终组合成完整的文件。 8. 关闭连接。文件传输完成后,关闭与客户端的连接,释放相关资源。 需要注意的是,以上只是一个简单文件传输服务器的基本流程。实际上,你可能还需要考虑错误处理、并发连接、文件权限等其他方面的问题。此外,为了提高性能和安全性,你还可以对文件传输进行优化和加密处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

stone8761

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值