Socket 服务器客户端文件传输

2019-12-18  本文已影响0人  wjundong

服务器部分

#include <sys/socket.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>


int sendFile(int sockfd, const char *filename)
{
    // 打开文件
    FILE *fp = fopen(filename, "r");
    if(fp < 0) {
        printf("open file failed!\n");
        return -1;
    }
    
    // 获取并发送文件大小信息
    fseek(fp, 0, SEEK_END);
    long fsize = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    
    if(send(sockfd, &fsize, sizeof(long), 0) != sizeof(long)) {
        printf("error: send file size failed!\n");
        fclose(fp);
        return -1;
    }

    // 发送文件主体
    char buf[512];
    long n, count = 0;
    while((n=fread(buf, 1, 512, fp)) > 0)
        send(sockfd, buf, n, 0);

    fclose(fp);
    return 0;
}


char *recvString(int sockfd)
{
    long len = 0;
    if(recv(sockfd, &len, sizeof(long), 0) != sizeof(long)) {
        printf("send string size failed!\n");
        return NULL;
    }

    char *string = (char *)malloc(len+1);
    if(string == NULL) {
        printf("malloc string failed!\n");
        return NULL;
    }
    
    if(recv(sockfd, string, len, 0) != len) {
        printf("recv string failed!\n");
        return NULL;
    }
    string[len] = '\0';
    return string;
}


int main()
{
    int sockfd;
    struct sockaddr_in serAddr, cliAddr;

    // 创建套接字描述符
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        printf("socket creation failed...\n"); 
        return 1; 
    }

    // 设置服务器地址和端口
    serAddr.sin_family = AF_INET;
    serAddr.sin_addr.s_addr = inet_addr("127.10.25.5"); 
    serAddr.sin_port = htons(8085);
    
    // 将服务器地址和端口与 sockfd 绑定
    if(bind(sockfd, (struct sockaddr*)&serAddr, sizeof(serAddr)) != 0) {
        printf("socket bind failed...\n"); 
        return 1; 
    }

    // 设置监听
    if(listen(sockfd, 5) != 0) {
        printf("listen failed...\n"); 
        return 1;
    }

    // 挂起捕获
    int connfd, len = sizeof(cliAddr);
    if((connfd = accept(sockfd, (struct sockaddr*)&cliAddr, &len)) > 0) {
        printf("connected %s port %d\n", inet_ntoa(cliAddr.sin_addr), ntohs(cliAddr.sin_port));
    }

    // 发送文件
    sendFile(connfd, "music.mp3");

    char *recvMsg = recvString(connfd);
    printf("%s\n", recvMsg != NULL ? recvMsg : "error");

    close(connfd);

    return 0;
}

客户端部分

#include <sys/socket.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>


int recvFile(int sockfd, const char *filename) 
{
    // 新建文件
    FILE *fp = fopen(filename, "w");
    if(fp == NULL) {
        printf("open file failed!\n");
        return -1;
    }

    // 先获取文件大小
    long fsize = 0;
    if(recv(sockfd, &fsize, sizeof(long), 0) != sizeof(long)) {
        printf("error: recv file size failed!\n");
        fclose(fp);
        return -1;
    }

    // 获取文件
    char buf[1024];
    long n, count = 0;
    while(count < fsize && (n = recv(sockfd, buf, 1024, 0))>0) {
        fwrite(buf, 1, n, fp);
        count += n;
    }

    fclose(fp);
    return 0;
}



int sendString(int sockfd, const char *string)
{  
    if(string == NULL)
        return -1;

    long len = strlen(string);
    if(send(sockfd, &len, sizeof(long), 0) != sizeof(long)) {
        printf("send string size failed!\n");
        return -1;
    }

    if(send(sockfd, string, len, 0) != len) {
        printf("send string failed!\n");
        return -1;
    }

    return 0;
}


int main()
{
    int sockfd;
    struct sockaddr_in serverAddr;

    // 创建套接字描述符
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        printf("socket creation failed...\n"); 
        return 1; 
    }

    // 设置要连接的服务器地址和端口
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr("127.10.25.5");
    serverAddr.sin_port = htons(8085);
    
    // 进行连接
    if (connect(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) != 0) { 
        printf("connection with the server failed...\n"); 
        return 1; 
    }

    // 接收文件
    recvFile(sockfd, "mymusic.mp3");

    // 发送消息
    sendString(sockfd, "I recvived!");

    close(sockfd);

    return 0;
}

有时候端口绑定失败,可以强制绑定

int opt = 1;
// 强制将套接字连接到 8080 端口
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,  &opt, sizeof(opt))) { 
    perror("setsockopt"); 
    exit(EXIT_FAILURE); 
} 
上一篇 下一篇

猜你喜欢

热点阅读