Windows网络编程之winsock实现文件传输示例

本文实例展示了Windows网络编程中winsock实现文件传输的方法,对于进行Windows下的winsock网络编程有一定的借鉴参考价值。

该程序代码主要是基于TCP流协议的winsock网络文件传输示例,采用Windows下的C语言编写。可以实现传递任何格式文件的文件传输功能。

具体实现代码如下:

Server端代码如下:

/*************************************************************************
  > File Name: Win_Server.c
  > Author: SongLee
 ************************************************************************/ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <WinSock2.h> 

#define PORT 8087
#define SERVER_IP "127.0.0.1"
#define BUFFER_SIZE 1024
#define FILE_NAME_MAX_SIZE 512
#pragma comment(lib, "WS2_32") 

int main()
{
  // 声明并初始化一个服务端(本地)的地址结构
  sockaddr_in server_addr;
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.S_un.S_addr = INADDR_ANY;
  server_addr.sin_port = htons(PORT); 

  // 初始化socket dll
  WSADATA wsaData;
  WORD socketVersion = MAKEWORD(2, 0);
  if(WSAStartup(socketVersion, &wsaData) != 0)
  {
    printf("Init socket dll error!");
    exit(1);
  } 

  // 创建socket
  SOCKET m_Socket = socket(AF_INET, SOCK_STREAM, 0);
    if (SOCKET_ERROR == m_Socket)
    {
      printf("Create Socket Error!");
    exit(1);
    } 

  //绑定socket和服务端(本地)地址
  if (SOCKET_ERROR == bind(m_Socket, (LPSOCKADDR)&server_addr, sizeof(server_addr)))
  {
    printf("Server Bind Failed: %d", WSAGetLastError());
    exit(1);
  } 

  //监听
  if (SOCKET_ERROR == listen(m_Socket, 10))
  {
    printf("Server Listen Failed: %d", WSAGetLastError());
    exit(1);
  } 

  while(1)
  {
    printf("Listening To Client...\n"); 

    sockaddr_in client_addr;
    int client_addr_len = sizeof(client_addr); 

    SOCKET m_New_Socket = accept(m_Socket, (sockaddr *)&client_addr, &client_addr_len);
    if (SOCKET_ERROR == m_New_Socket)
    {
      printf("Server Accept Failed: %d", WSAGetLastError());
      break;
    } 

 char buffer[BUFFER_SIZE];
 memset(buffer, 0, BUFFER_SIZE);
    if (recv(m_New_Socket, buffer, BUFFER_SIZE, 0) < 0)
    {
      printf("Server Receive Data Failed!");
      break;
    } 

    char file_name[FILE_NAME_MAX_SIZE+1];
    memset(file_name, 0, FILE_NAME_MAX_SIZE+1);
    strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE:strlen(buffer));
    printf("%s\n", file_name); 

    FILE * fp = fopen(file_name, "rb"); //windows下是"rb",表示打开一个只读的二进制文件
    if (NULL == fp)
    {
      printf("File: %s Not Found\n", file_name);
    }
        else
    {
      memset(buffer, 0, BUFFER_SIZE);
      int length = 0; 

      while ((length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)
      {
        if (send(m_New_Socket, buffer, length, 0) < 0)
        {
          printf("Send File: %s Failed\n", file_name);
          break;
        }
        memset(buffer, 0, BUFFER_SIZE);
      } 

      fclose(fp);
      printf("File: %s Transfer Successful!\n", file_name);
    }
    closesocket(m_New_Socket);
  } 

  closesocket(m_Socket);
  //释放winsock库
  WSACleanup();
  return 0;
}

Client端代码如下:

/*************************************************************************
  > File Name: Win_Client.c
  > Author: SongLee
 ************************************************************************/ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <WinSock2.h> 

#define PORT 8087
#define SERVER_IP "127.0.0.1"
#define BUFFER_SIZE 1024
#define FILE_NAME_MAX_SIZE 512
#pragma comment(lib, "WS2_32") 

int main()
{
  // 初始化socket dll
  WSADATA wsaData;
  WORD socketVersion = MAKEWORD(2, 0);
  if(WSAStartup(socketVersion, &wsaData) != 0)
  {
    printf("Init socket dll error!");
    exit(1);
  } 

  //创建socket
  SOCKET c_Socket = socket(AF_INET, SOCK_STREAM, 0);
  if (SOCKET_ERROR == c_Socket)
  {
    printf("Create Socket Error!");
    system("pause");
    exit(1);
  } 

  //指定服务端的地址
  sockaddr_in server_addr;
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.S_un.S_addr = inet_addr(SERVER_IP);
  server_addr.sin_port = htons(PORT); 

  if (SOCKET_ERROR == connect(c_Socket, (LPSOCKADDR)&server_addr, sizeof(server_addr)))
  {
    printf("Can Not Connect To Server IP!\n");
    system("pause");
    exit(1);
  } 

  //输入文件名
  char file_name[FILE_NAME_MAX_SIZE+1];
  memset(file_name, 0, FILE_NAME_MAX_SIZE+1);
  printf("Please Input File Name On Server: ");
  scanf("%s", &file_name); 

  char buffer[BUFFER_SIZE];
  memset(buffer, 0, BUFFER_SIZE);
  strncpy(buffer, file_name, strlen(file_name)>BUFFER_SIZE ? BUFFER_SIZE:strlen(file_name)); 

  //向服务器发送文件名
  if(send(c_Socket, buffer, BUFFER_SIZE, 0) < 0)
  {
    printf("Send File Name Failed\n");
    system("pause");
    exit(1);
  } 

  //打开文件,准备写入
  FILE * fp = fopen(file_name, "wb"); //windows下是"wb",表示打开一个只写的二进制文件
  if(NULL == fp)
  {
    printf("File: %s Can Not Open To Write\n", file_name);
    system("pause");
    exit(1);
  }
  else
  {
    memset(buffer, 0, BUFFER_SIZE);
    int length = 0;
    while ((length = recv(c_Socket, buffer, BUFFER_SIZE, 0)) > 0)
    {
      if (fwrite(buffer, sizeof(char), length, fp) < length)
      {
        printf("File: %s Write Failed\n", file_name);
        break;
      }
      memset(buffer, 0, BUFFER_SIZE);
    } 

    printf("Receive File: %s From Server Successful!\n", file_name);
  } 

  fclose(fp);
  closesocket(c_Socket); 

  //释放winsock库
  WSACleanup(); 

  system("pause");
  return 0;
}

程序中备有较为详尽的注释,相信大家不难理解。感兴趣的朋友可以根据自身需要对程序加以灵活改善,使其功能更加强大。

(0)

相关推荐

  • Windows和Linux下定时删除某天前的文件的脚本

    以前做到最多的定时我们就是定时备份功能了,我们常用利用定时功能来备份网站数据或备份数据库了,下面我来给(www.jb51.net)大家介绍几个Linux与Windows中定时删除某天前的文件方法,这个与备份有点区别,但大同小义了. Windows下bat文件内容如下: 复制代码 代码如下: @echo off forfiles -p "D:\servers\apache2.2\logs" -s -m *.log -d -15 -c "cmd /c del @path"

  • Windows批处理中获取文件属性的一些方法

    windows的batchfile可以有%0-%9参数,其中%0默认表示batchfile的全路径,%1-%9为用户的传入参数. 以下特殊标记可以用来获得文件的属性,如果对%0使用特殊标记,表示获得batachfile的相关属性,如果%1-%9中某个%*是个文件的路径,也可以使用如下特殊标记来获得%*表示文件的相关属性. 例如:D:\testfolder\test.bat 复制代码 代码如下: echo off echo path name: echo %1 echo fully qualifi

  • Windows Server 2003服务器无法下载.exe文件的解决方法

    今天架设了一台Windows Server 2003的网站服务器,发现打开网页后无法下载网站中的.exe文件,经过研究问题得以解决,拿来做个备忘. 解决方法非常简单,只需要在IIS中,将网站属性里的执行权限设置为"纯脚本"即可. 附:Windows Server 2003服务器无法下载EXE为后缀的文件解决办法 实际操作过程中只进行了第二步就成功了, 即:打开iis管理器,右键网站-点击属性-主目录,将执行权限设置为"无"或者"纯脚本",即取消&

  • Windows误删文件恢复技巧

    如果只能使用Windows本身提供的工具,那么我们可以认为清空回收站之后,被删除的文件已经彻底清除了.不过事实并非如此,只要有专用的硬件和软件,即使数据已经被覆盖.驱动器已经重新格式化.引导扇区彻底损坏,或者磁盘驱动器不再运转,我们还是可以恢复几乎所有的文件. 一.磁盘如何保存数据 要理解如何恢复已删除的数据,首先要搞清楚磁盘如何保存数据.硬盘驱动器里面有一组盘片,数据就保存在盘片的磁道(Track)上,磁道在盘片上呈同心圆分布,读/写磁头在盘片的表面移动访问硬盘的各个区域,因此文件可以随机地分

  • 备份和恢复Windows IIS服务器设置的方法

    我们在使用Windows 2000 Server自带的IIS(Internet Information Server,Internet信息服务器)时,经常需要设置一些Web服务.FTP服务等,但是经过一段时间的使用之后,Web站点.FTP站点.虚拟目录比较多了,其配置也变得越来越复杂.IIS能不能恢复到以前的状态呢?答案是肯定的. 备份IIS设置:IIS本身自带了备份和恢复IIS设置的功能.在恢复IIS设置之前需要备份IIS.备份的过程很简单:在Windows 2000 Server中找到"开始

  • 在Windows中配置Rsync同步文件的方法

    Rsync是一款不错的文件免费同步软件,可以镜像保存整个目录树和文件系统,同时保持原来文件的权限.时间.软硬链接.第一次同步时 rsync 会复制全部内容,下次只传输修改过的文件部分.传输数据过程中可以实行压缩及解压缩操作,减少带宽流量.支持scp.ssh及直接socket方式连接,支持匿名传输.支持Linux,Window平台.写本文的时候,window版最新版为4.0.5版 官网:http://rsync.samba.org/ Linux版下载:http://rsync.samba.org/

  • Windows Powershell 执行文件和脚本

    象运行可执行文件一样,Powershell运行文件和脚本,也必须使用绝对路径或者相对路径,或者要运行的文件必须定义在可受信任的环境变量中. 关于脚本 脚本和批处理都属于伪可执行文件,它们只是包含了若干命令行解释器能够解释和执行的命令行代码. 执行批处理文件 批处理是扩展名为".bat"的文本文件,它可以包含任何cmd控制台能够处理的命令.当批处理文件被打开,Cmd控制台会逐行执行每条命令.那Powershell能够直接执行批处理吗? 将下列命令保存为ping.bat @echo off

  • Windows 2000、XP、2003登录密码恢复攻略

    一.删除SAM文件,清除Administrator账号密码 二.从SAM文件中查找密码        1.L0phtCrack (LC)        2.LCP        3.SamInside pro 三.用Net User命令恢复系统登陆用户密码 四.用密码重设盘设新密码 五.修改屏保文件法 六.使用软件修改密码 Windows XP 2000 NT Password Recovery Key CleanPwd Offline NT Password & Registry Editor

  • Windows下的PHP安装文件线程安全和非线程安全的区别

    从2000年10月20日发布的第一个Windows版的PHP3.0.17开始的都是线程安全的版本,这是由于与Linux/Unix系统是采用 多进程的工作方式不同的是Windows系统是采用多线程的工作方式.如果在IIS下以CGI方式运行PHP会非常慢,这是由于CGI模式是建立在多进程 的基础之上的,而非多线程.一般我们会把PHP配置成以ISAPI的方式来运行,ISAPI是多线程的方式,这样就快多了.但存在一个问题,很多常用的 PHP扩展是以Linux/Unix的多进程思想来开发的,这些扩展在IS

  • 二十九、教你备份与恢复Windows 2000注册表

    二十九.教你备份与恢复Windows 2000注册表  Windows 2000将它的配置信息存储在注册表的数据库中,其中包含了每个计算机用户的配置文件,以及有关系统硬件.已安装的程序和属性设置等信息,Windows 2000在运行过程中要一直引用这些信息.注册表是以二进制形式存储在硬盘上,错误地编辑注册表可能会严重损坏系统.所以,在更改注册表之前,强烈建议备份注册表信息.为了防止在修改注册表的时候发生致命错误,有必要了解一下注册表文件的备份和恢复方法.除此之外,为了研究注册表的结构,还可以将注

随机推荐