linux TCPIP 多线程下载 实验代码

本文介绍了一种基于TCP协议的客户端与服务器之间的文件传输实现方法。通过C语言编程,利用多线程技术实现了文件的高效传输。文章详细展示了client.c和server.c的代码结构,包括连接建立、文件发送与接收等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编译方式:

client : gcc -o client client.c tcpfd.c

server: gcc -o server server.c tcpfd.c

可直接无参在自己机器运行,默认127.0.0.1:1029 client.c文件,其他方式参数输入方式见代码

1.client.c

#include "head.h"
#include "tcpfd.h"

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

        char *servaddr;
        int port;
        int clientfd;
        char msg[MSG_SIZE];

        if (argc < 4){
                servaddr = (char *)"127.0.0.1";//地址
                port = 1029;//端口
                strcpy(msg, "client.c");//文件名
        }
        else{
                servaddr = argv[1];
                port = atoi(argv[2]);
                strcpy(msg, argv[3]);
        }
        printf("------------Client started------------\n");
        printf("Server Info:\n");
        printf("Address: %s    Port: %d\n", servaddr, port);

        if ((clientfd = open_clientfd(servaddr, port)) < 0){
                printf("Connect error \n");
                exit(1);
        }
        //transmission
        send_msg(clientfd, msg);
        rev_file(clientfd, msg);

        printf("Connect closed \n");
        printf("------------Client closed------------\n");
        exit(0);
}


2.server.c

#include "head.h"
#include "tcpfd.h"
/*
            编译指令:
        cc main.c -o server.o -lpthread
*/
void *thread_l1(void *vargp);

int main(int argc, char **argv)
{
        int listenfd;
        int port;
        struct sockaddr_in clientaddr;
        int clientlen;
        int *connectedfdp;
        struct hostent *hp;
        char *hpaddr;
        //thread
        pthread_t tid_l1;

        if (argc < 2){
                port = 1029;
        }
        else{
                port = atoi(argv[1]);
        }
        printf("------------Server started------------\n");
        printf("Server Info: \n");
        printf("Port: %d\n", port);
        if ((listenfd = open_listenfd(port)) < 0){
                printf("server create error\n");
                exit(1);
        }

        while(1){
                clientlen = sizeof(struct sockaddr_in);
                connectedfdp = (int *)malloc(sizeof(int));
                *connectedfdp = accept(listenfd, (struct sockaddr *)&clientaddr, (socklen_t *)&clientlen);

                hp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
                                   sizeof(clientaddr.sin_addr.s_addr), AF_INET);
                hpaddr = inet_ntoa(clientaddr.sin_addr);
                printf("Client connected from %s ==> %s\n", hp->h_name, hpaddr);
                //thread & semaphore
                pthread_create(&tid_l1, NULL, thread_l1, connectedfdp);
        }
        printf("------------Server closed------------\n");
        exit(0);
}

void *thread_l1(void *vargp)
{
        static int pcnt = 0;
        int connectfd_tl1 = *((int *)vargp);
        pthread_detach(pthread_self());
        free(vargp);
        char msg[MSG_SIZE];
        char *filename = recv_msg(connectfd_tl1, msg);
        printf("Thread %d:\n", pcnt);
        pcnt++;
        send_file(connectfd_tl1, filename);
        printf("\n");
        close(connectfd_tl1);

        return NULL;
}
3.tcpfd.c

#include "head.h"
#include "tcpfd.h"

int open_clientfd(char *servname, int port)
{
        int clientfd;
        struct hostent *hp;
        struct sockaddr_in servaddr;
        struct in_addr addr;

        if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
                printf("open_clientfd: socket error");
                return -1;
        }

        if (inet_aton(servname, &addr) != 0)
                hp = gethostbyaddr((const char *)&addr, sizeof(addr), AF_INET);
        else
                hp = gethostbyname(servname);

        bzero((char *)&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        bcopy((char *)hp->h_addr_list[0],
              (char *)&servaddr.sin_addr.s_addr, hp->h_length);
        servaddr.sin_port = htons(port);

        if (connect(clientfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){
                printf("open_clientfd: connect error\n");
                return -1;
        }

        printf("Connect created.\n");
        return clientfd;
}

void rev_file(int fd, char *filename)
{
        char buffer[BUFFER_SIZE];
        FILE *fp = fopen(filename, "w");
        if (fp == NULL)
        {
                printf("File: %s Can Not Open To Write!\n", filename);
                exit(1);
        }

        // 从服务器端接收数据到buffer中
        bzero(buffer, sizeof(buffer));
        int length = 0;
        while((length = recv(fd, buffer, BUFFER_SIZE, 0)) > 0)
        {

                int write_length = fwrite(buffer, sizeof(char), length, fp);
                if (write_length < length)
                {
                        printf("File: %s Write Failed!\n", filename);
                        break;
                }
                bzero(buffer, BUFFER_SIZE);
        }
        if (length < 0)
        {
                printf("Recieve Data From Server Failed!\n");
        }

        printf("Recieve File: %s From Server Finished!\n", filename);

        // 传输完毕,关闭socket
        fclose(fp);
        close(fd);
}

void send_msg(int fd, char *msg)
{
    if (send(fd, msg, strlen(msg), 0) < 0)
    {
            printf("send_msg: %s Failed!\n", msg);
            return;
    }
    printf("MSG Sended: %s\n", msg);
}

int open_listenfd(int port)
{

        int listenfd;
        int optval = 1;
        struct sockaddr_in servaddr;

        if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
                printf("open_listenfd: listenfd socket error\n");
                return -1;
        }

        if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof(int)) < 0){
                printf("open_listenfd: setsockopt error\n");
                return -1;
        }

        bzero((char *)&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons((unsigned int)port);


        if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr))<0){
                printf("open_listenfd: bind error\n");
                return -1;
        }

        if(listen(listenfd, 16)<0){
                printf("open_listenfd: listen error\n");
                return -1;
        }

        printf("------------Server Created------------\n");
        printf("\n");
        return listenfd;
}

void send_file(int fd, char *filename)
{
        char buffer[BUFFER_SIZE];
        printf("send File: %s \n", filename);
        FILE *fp = fopen(filename, "r");
        if (fp == NULL)
        {
                printf("File: %s Not Found!\n", filename);
        }
        else
        {
                bzero(buffer, BUFFER_SIZE);
                int file_block_length = 0;
                while( (file_block_length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)
                {
                        //printf("file_block_length = %d\n", file_block_length);

                        // 发送buffer中的字符串到fd,实际上就是发送给客户端
                        if (send(fd, buffer, file_block_length, 0) < 0)
                        {
                                    printf("Send File: %s Failed!\n", filename);
                                    break;
                        }

                        bzero(buffer, sizeof(buffer));
                }
                fclose(fp);
                printf("File: %s Transfer Finished!\n", filename);
        }
}

char* recv_msg(int fd, char msg[])
{
        int length;
        bzero(msg, MSG_SIZE);
        if ((length = recv(fd, msg, MSG_SIZE, 0)) < 0)
        {
                printf("recv_msg: %s Failed!\n", msg);
        }
        printf("MSG Recveived: %s \n", msg);
        return msg;
}

4.tcpfd.h

#define BUFFER_SIZE 1024
#define MSG_SIZE    128

int open_clientfd(char *servname, int port);
void rev_file(int fd, char *filename);
void send_msg(int fd, char *msg);
int open_listenfd(int port);
void send_file(int fd, char *filename);
char* recv_msg(int fd, char msg[]);

5.head.h

#ifndef __HEAD_H__
#define __HEAD_H__

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <math.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#endif


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值