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);
}

 

 

 

 

 

  

 

posted @ 2013-04-01 23:00  shuimuouyang  阅读(413)  评论(0编辑  收藏  举报