• C语言通过网络实现发送文件的一点记录


    Code First.

    Server.c代码分析。

      

      1.引入一些头文件和dll.

        

    #include <winsock2.h>
    #include <stdio.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    
    #pragma comment(lib, "ws2_32.lib")

      2.服务器建立Socket套接字

      

        

    View Code
    void main(void){
    
        WSADATA            wsaData;
        SOCKET            MainSocket;//Socket对象
        SOCKADDR_IN        sin;//Socket结构
        int                Port = 5151;//端口
        int                Ret;//返回值
    
    
        // 初始化,加载系统资源
        if ((Ret = WSAStartup(MAKEWORD(2,2),&wsaData) != 0)) {
            printf("WSAStartup 失败: %d\n",Ret);
            return ;
        }
    
        //创建套接字
        if ((MainSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == INVALID_SOCKET) {
        
            printf("Socket 创建失败: %d\n",WSAGetLastError());
            WSACleanup();//回收资源
            return ;
        }
    
        //填充sockaddr_in结构
        sin.sin_family = AF_INET;
        sin.sin_port = htons(Port);
        sin.sin_addr.s_addr = htonl(INADDR_ANY);//操作系统分配地址
    
        //绑定地址
        if (bind(MainSocket,(SOCKADDR *)&sin,sizeof(sin)) == SOCKET_ERROR) {
        
            printf("绑定失败: %d\n",WSAGetLastError());
            WSACleanup();
            return ;
        }
    
        //监听
        if ( listen(MainSocket,5) == SOCKET_ERROR) {
            printf("监听失败:    %d\n",WSAGetLastError());
            return ;
        }
    
        printf("We are awaiting a connection on port %d.\n", Port);
    
    
        // 循环处理客户连接请求
    
    
        while(1) {
        
            SOCKADDR_IN        ClientAddr;//声明新的Socket结构体
            int                ClientAddrLen = sizeof(ClientAddr);//结构体长度
    
            // 接收新的客户机,返回与客户机连接的套接字
    
            SOCKET NewConnection = 
                accept(MainSocket,(SOCKADDR *)&ClientAddr,&ClientAddrLen);
            if (NewConnection == INVALID_SOCKET) {
                continue;//结束当前循环,进入下一次,获取新的连接
            }
    
        
            // 启动交互线程
            CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MutilThread, (void*)NewConnection, 0, NULL);
            
    
        }
    
        
        //释放资源
    
        closesocket(MainSocket);
        WSACleanup();
    
    }    

      3.发送文件

    View Code
    char FileTrans1(SOCKET sock, char *filename) {
    
        char buf[8192];//缓冲数组
        FILE *fp;//文件指针
        struct _stat    info;//结构体描述
    
        int filesize ;//文件大小
        int res ;//发送结果
    
        int blocks ;//文件块
        int i;//循环索引
    
         _stat(filename,&info);//获取文件大小
    
         filesize = info.st_size;
    
         printf("文件大小: %d\n", filesize);
    
        fp = fopen(filename,"rb");
    
        if (fp == NULL) {
            printf("文件打开错误..\n");
            //    exit(1);
    
            return -1;
        }
    
        //发送文件大小
        res = send(sock,(char *)&filesize,sizeof(filesize),0);
    
        printf("发送大小: %d\n",res);
    
        //读文件
        blocks = filesize /sizeof(buf) + 1;
    
        printf("文件 blocks : %d\n",blocks);
    
        for(i = 0; i < blocks; i++) 
        {
            //清空缓冲区
            memset(buf,0,sizeof(buf));
            //读取一个数据块
            fread(buf,sizeof(buf),1,fp);
            //发送一个数据块
            res    = send(sock,buf,sizeof(buf),0);
            printf("第 %d 次发送: %d\n", i+1,res);
        }
    
        //发送完毕,关闭文件指针
        fclose(fp);
    
        return 0;
    }


    Client.c

      测试代码:

      

    View Code
    #include <stdio.h>
    #include <winSock2.h>
    #include <stdlib.h>
    #include <time.h>
    #include <sys/stat.h>
    
    #pragma comment(lib, "ws2_32.lib")
    
    
    /*  
        函数名:getFileSizeSystemCall(char * strFileName)     
        功能:获取指定文件的大小  
        参数:  
            strFileName (char *):文件名  
        返回值:  
            size (int):文件大小  
     */  
    int getFileSizeSystemCall(char * strFileName)    
    {   
        struct stat temp;   
        stat(strFileName, &temp);   
        return temp.st_size;   
    } 
    
    int getFileSize(char * strFileName){
    
    
        FILE *fp;
        int size;
        if ((fp = fopen(strFileName,"rb")) == NULL) 
        {
            printf("File open error\n");
            return 0;
        }
    
    
        fseek(fp,0L,SEEK_END);
        size = ftell(fp);
        
        fclose(fp);
        return size;
    }
    
    void RecvFile(SOCKET sock,char *filename);
    
    void main(void)
    {
           WSADATA              wsaData;
           SOCKET               s;
           SOCKADDR_IN          ServerAddr;
    
           int                  Port = 5151;
        
        //    char                msg1[128];
        //    char                msg2[128];
    
    
    
           WSAStartup(MAKEWORD(2,2), &wsaData);
       
       // 创建一个新的Socket来连接服务器
     
          s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
       
       // 填写客户端地址信息
       // 端口为5150
       // 服务器IP地址为"136.149.3.29",注意使用inet_addr将IP地址转换为网络格式
    
          ServerAddr.sin_family = AF_INET;
          ServerAddr.sin_port = htons(Port);    
          ServerAddr.sin_addr.s_addr = inet_addr("10.160.17.141");//192.168.1.103
    
       // 向服务器发出连接请求
    
          if ( connect(s, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr)) ==
              SOCKET_ERROR) 
          {
                printf("Connection Error....\n");
                return ;
          } 
    
          printf("Connectd....\n");
        
    
        //    recv(s,msg1,sizeof(msg1),0);
        //    recv(s,msg2,sizeof(msg2),0);
    
        //    printf("msg = %s\n",msg1);
        //    printf("msg = %s\n",msg2);
    
    
    
         RecvFile(s,"G:\\test.rmvb");
    
    
          // 新的连接建立后,就可以互相通信了,在这个简单的例子中,我们直接关闭连接,
         // 并关闭监听Socket,然后退出应用程序
    
          closesocket(s);
         // 释放Windows Socket DLL的相关资源
          WSACleanup();
          getchar();
    }
    
    
    void RecvFile(SOCKET sock,char *filename){
        
    
        FILE *fp;//文件指针
        char buf[8192];//缓冲区
    
        int filesize ;
        int blocks;
        int i;
        int res;
        int count ;
    
        printf("开始接收文件..\n");
    
        //接收文件大小
        recv(sock,(char *)&filesize,sizeof(filesize),0);
    
        printf("接收文件大小: %d\n",filesize);
        
        fp = fopen(filename,"wb+");
        if (fp == NULL) {
                printf("Client...文件打开错误..\n");
                exit(1);
        }
    
        //接收数据
        blocks = filesize / sizeof(buf) + 1;
    
        printf("块大小: %d\n",blocks);
    
        for (i=0; i<blocks;++i) {
        
            //清空缓冲区
            memset(buf,0,sizeof(buf));
            //接收数据
            res = recv(sock,buf,sizeof(buf),0);
            //写入数据
            count = fwrite(buf,sizeof(buf),1,fp);
    
            printf("第 %d 次是否写入: %d\n",i+1,count);
            printf("第 %d 次接收: %d\n", i+1,res);
        }
    
        //关闭文件
        fclose(fp);
    }

      

  • 相关阅读:
    二叉树的前序、中序、后序遍历
    队列&优先队列
    angularJS 初始化
    angularJS $q
    获取checkbox返回值
    ngRoute
    两个类的装饰器,内置的魔术方法
    super封装property反射
    广度优先和深度优先 父类对子类的约束 多态 鸭子模型
    继承
  • 原文地址:https://www.cnblogs.com/scherrer/p/2994505.html
Copyright © 2020-2023  润新知