用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字

芙蓉妹妹    -  云代码空间

——

利用TCP完成linux和windows平台的文件传输

2018-11-05|930阅||

摘要:利用循环面向连接完成linux和windows平台的文件传输(考虑服务器地址、端口号的设定方式);完成客户端、服务器端代码的封装。

一、服务端(Linuxserver.c)

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/socket.h>

#include <netinet/in.h>

#define PORT 8888

#define LISTENQ 20

#define BUFFSIZE 4096

#define FILE_NAME_MAX_SIZE 512

int passiveTCP (const int service){

    //Create socket

    int sockfd,connfd;

    struct sockaddr_in svraddr,clientaddr;

    bzero(&svraddr,sizeof(svraddr));

    svraddr.sin_family=AF_INET;

    svraddr.sin_addr.s_addr=htonl(INADDR_ANY);

    svraddr.sin_port=htons(PORT);

    sockfd=socket(AF_INET,SOCK_STREAM,0);

    if(sockfd<0)

    {

        perror("socket");

        exit(1);

    }

    if(bind(sockfd,(struct sockaddr*)&svraddr,sizeof(svraddr))<0) //bind

    {

        perror("bind");

        exit(1);

    }

    if(listen(sockfd,LISTENQ)<0)//listen

    {

        perror("listen");

        exit(1);

    }

    return sockfd;

}

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

{

    //Input the file name

    char filename[FILE_NAME_MAX_SIZE];

    bzero(filename,FILE_NAME_MAX_SIZE);

    printf("Please input the file name you wana to send:");

    scanf("%s",filename);

    getchar();

    int sockfd,connfd;

    struct sockaddr_in clientaddr;

    sockfd = passiveTCP(PORT);

    while(1)

    {

        socklen_t length=sizeof(clientaddr);

        connfd=accept(sockfd,(struct sockaddr*)&clientaddr,&length);//accept

        if(connfd<0)

        {

            perror("connect");

            exit(1);

        }

        //send file imformation

        char buff[BUFFSIZE];

        int count;

        bzero(buff,BUFFSIZE);

strncpy(buff,filename,strlen(filename)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(filename));

        count=send(connfd,buff,BUFFSIZE,0);

        if(count<0)

        {

            perror("Send file information");

            exit(1);

        }

        FILE *fd=fopen(filename,"rb");//read file

        if(fd==NULL)

            printf("File :%s not found!\n",filename);

        else

        {

            bzero(buff,BUFFSIZE);

            int file_block_length=0;

            while((file_block_length=fread(buff,sizeof(char),BUFFSIZE,fd))>0)

            {

                printf("file_block_length:%d\n",file_block_length);

                if(send(connfd,buff,file_block_length,0)<0)

                {

                    perror("Send");

                    exit(1);

                }

                bzero(buff,BUFFSIZE);   

            }

            fclose(fd);

            printf("Transfer file finished !\n");

        }

        close(connfd);

    }

    close(sockfd);

    return 0;

}

二、客户端(Windowsclient.c)

#include <stdlib.h>

#include <winsock2.h>

#include <stdio.h>

#define IP "192.168.91.128"         //在一台计算机上测试,IPLinux服务器地址

#define PORT 8888                /注意:客户端设置通信的端口 = 服务端的端口

#define BUFFER_SIZE 1024            //数据发送缓冲区大小

#define LISTENQ 20

#define BUFFSIZE 4096

#define FILE_NAME_MAX_SIZE 512

void recvTCP(int clientfd){

    //recv file imformation

    char buff[BUFFSIZE];

    char filename[FILE_NAME_MAX_SIZE];//文件名称

    int count;

    memset(buff,0,BUFFSIZE);//buff中前BUFFSIZE个字改成0。清空地址结构

    count=recv(clientfd,buff,BUFFSIZE,0);//clientfd套接字中接受数据,存在长度为BUFFSIZEbuff中,最后一个参数一般为0recv函数仅仅是copy数据,真正的接收数据是协议来完成的,返回其实际copy的字节数;如果recvcopy时出错,那么它返回SOCKET_ERROR

    if(count<0)

    {

        perror("recv");

        exit(1);

    }

    count  = strlen(buff) > FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE : strlen(buff) ; //传输文件名的长度

    memcpy(filename,buff,count);//buff所指向的字符串中以buff地址开始的前若干(最后一个参数长)个字节复制到filename所指的数组中,并返回被复制后的filename

    filename[count] = '\0';//如果buff长度小于filename长度,只是将buffcount个字符复制过去,不自动添加'\0',需手动添加

    printf("Preparing recv file : %s \n",filename);

    //recv file

    FILE *fd=fopen(filename,"wb+");//打开文件

    if(NULL==fd)

    {

        perror("open");

        exit(1);

    }

    memset(buff,0,BUFFSIZE);//清空地址结构,准备接受文件内容

    int length=0;

    while(length=recv(clientfd,buff,BUFFSIZE,0))//接受

    {

        if(length<0)

        {

            perror("recv");

            exit(1);

        }

        int writelen=fwrite(buff,sizeof(char),length,fd);//往文件里写内容

        if(writelen<length)

        {

            perror("write");

            exit(1);

        }

        memset(buff,0,BUFFSIZE);//清空地址结构

    }

    printf("Receieved file: %s  finished!\n",filename);

    fclose(fd);

}

int connectTCP(const char *host, const int port){

       WSADATA WSAData;

        if(WSAStartup(MAKEWORD(2,0),&WSAData)==SOCKET_ERROR)  //WSAStartup()函数对Winsock DLL进行初始化

        {

            printf("Socket initialize fail!\n");

            //continue;

        }

        SOCKET sock;                              //客户端进程创建套接字

        if((sock=socket(AF_INET,SOCK_STREAM,0))==SOCKET_ERROR)  //创建流套接字(与服务端保持一致)

        {

            printf("Socket create fail!\n");

            WSACleanup();

            //continue;

        }

        struct sockaddr_in ClientAddr;         //sockaddr_in结构用来标识TCP/IP协议下的地址,可强制转换为sockaddr结构

        ClientAddr.sin_family=AF_INET;      //Internet,地址类型为AF_INET

        ClientAddr.sin_port=htons(PORT);         //指定服务端所预留的端口

        ClientAddr.sin_addr.s_addr=inet_addr(IP);   //指定服务端所绑定的IP地址    if(connect(sock,(LPSOCKADDR)&ClientAddr,sizeof(ClientAddr))==SOCKET_ERROR)  //调用connect()函数,向服务器进程发出连接请求

        {

            printf("Connect fail!\n");

            closesocket(sock);

            WSACleanup();

            //continue;

        }

        return sock;

}

int main()

{

    SOCKET sock;                        //客户端进程创建套接字

    char buf[BUFFER_SIZE];               //buf数组存放客户端发送的消息

    int inputLen;                          //用于输入字符自增变量

    while(1)

    {

        printf("Socket\\Client>");

        inputLen=0;

        memset(buf,0,sizeof(buf));//清空地址结构

        while((buf[inputLen++]=getchar())!='\n')        //输入以回车键为结束标识

        {

            ;

        }

        if(buf[0]=='e' && buf[1]=='x' && buf[2]=='i' && buf[3]=='t')

        {

            printf("The End.\n");

            break;

        }

        sock=connectTCP(IP,PORT);

        recvTCP(sock);

        closesocket(sock);                           //关闭套接字

      WSACleanup(); //终止对Winsock DLL的使用,并释放资源,以备下一次使用

    }

    return 0;

}

三、实验截屏

Linux服务端:

Windows客户端:

实验前无test.txt文件:

实验后:

顶 2踩 2收藏
文章评论
    发表评论

    个人资料

    • 昵称: 芙蓉妹妹
    • 等级: 资深程序员
    • 积分: 1710
    • 代码: 104 个
    • 文章: 25 篇
    • 随想: 0 条
    • 访问: 32 次
    • 关注

    标签

    最新提问

      站长推荐