Linux下使用socket传输文件的C语言简单实现

转载:http://blog.csdn.net/ljd_1986413/article/details/7940938

服务器程序和客户端程序应当分别运行在两台计算机上。

在运行服务器端的计算机终端执行:./file_server

在运行客户端的计算终端上执行:./file_client   ipaddr_server

然后根据提示输入要传输的服务器上的文件,该文件必须在服务器的当前运行目录中,否则会提示找不到文件。

 

直接上源码吧:

 

[cpp] view plaincopy
  1.   
  2. // file_server.c -- socket文件传输服务器端示例代码   
  3. // /  
  4. #include<netinet/in.h>   
  5. #include<sys/types.h>   
  6. #include<sys/socket.h>   
  7. #include<stdio.h>   
  8. #include<stdlib.h>   
  9. #include<string.h>   
  10.   
  11. #define HELLO_WORLD_SERVER_PORT    6666  
  12. #define LENGTH_OF_LISTEN_QUEUE     20  
  13. #define BUFFER_SIZE                1024  
  14. #define FILE_NAME_MAX_SIZE         512  
  15.   
  16. int main(int argc, char **argv)  
  17. {  
  18.     // set socket's address information   
  19.     // 设置一个socket地址结构server_addr,代表服务器internet的地址和端口  
  20.     struct sockaddr_in   server_addr;  
  21.     bzero(&server_addr, sizeof(server_addr));  
  22.     server_addr.sin_family = AF_INET;  
  23.     server_addr.sin_addr.s_addr = htons(INADDR_ANY);  
  24.     server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);  
  25.   
  26.     // create a stream socket   
  27.     // 创建用于internet的流协议(TCP)socket,用server_socket代表服务器向客户端提供服务的接口  
  28.     int server_socket = socket(PF_INET, SOCK_STREAM, 0);  
  29.     if (server_socket < 0)  
  30.     {  
  31.         printf("Create Socket Failed!\n");  
  32.         exit(1);  
  33.     }  
  34.   
  35.     // 把socket和socket地址结构绑定   
  36.     if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)))  
  37.     {  
  38.         printf("Server Bind Port: %d Failed!\n", HELLO_WORLD_SERVER_PORT);  
  39.         exit(1);  
  40.     }  
  41.   
  42.     // server_socket用于监听   
  43.     if (listen(server_socket, LENGTH_OF_LISTEN_QUEUE))  
  44.     {  
  45.         printf("Server Listen Failed!\n");  
  46.         exit(1);  
  47.     }  
  48.   
  49.     // 服务器端一直运行用以持续为客户端提供服务   
  50.     while(1)  
  51.     {  
  52.         // 定义客户端的socket地址结构client_addr,当收到来自客户端的请求后,调用accept  
  53.         // 接受此请求,同时将client端的地址和端口等信息写入client_addr中  
  54.         struct sockaddr_in client_addr;  
  55.         socklen_t          length = sizeof(client_addr);  
  56.   
  57.         // 接受一个从client端到达server端的连接请求,将客户端的信息保存在client_addr中  
  58.         // 如果没有连接请求,则一直等待直到有连接请求为止,这是accept函数的特性,可以  
  59.         // 用select()来实现超时检测   
  60.         // accpet返回一个新的socket,这个socket用来与此次连接到server的client进行通信  
  61.         // 这里的new_server_socket代表了这个通信通道  
  62.         int new_server_socket = accept(server_socket, (struct sockaddr*)&client_addr, &length);  
  63.         if (new_server_socket < 0)  
  64.         {  
  65.             printf("Server Accept Failed!\n");  
  66.             break;  
  67.         }  
  68.   
  69.         char buffer[BUFFER_SIZE];  
  70.         bzero(buffer, sizeof(buffer));  
  71.         length = recv(new_server_socket, buffer, BUFFER_SIZE, 0);  
  72.         if (length < 0)  
  73.         {  
  74.             printf("Server Recieve Data Failed!\n");  
  75.             break;  
  76.         }  
  77.   
  78.         char file_name[FILE_NAME_MAX_SIZE + 1];  
  79.         bzero(file_name, sizeof(file_name));  
  80.         strncpy(file_name, buffer,  
  81.                 strlen(buffer) > FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE : strlen(buffer));  
  82.   
  83.         FILE *fp = fopen(file_name, "r");  
  84.         if (fp == NULL)  
  85.         {  
  86.             printf("File:\t%s Not Found!\n", file_name);  
  87.         }  
  88.         else  
  89.         {  
  90.             bzero(buffer, BUFFER_SIZE);  
  91.             int file_block_length = 0;  
  92.             while( (file_block_length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)  
  93.             {  
  94.                 printf("file_block_length = %d\n", file_block_length);  
  95.   
  96.                 // 发送buffer中的字符串到new_server_socket,实际上就是发送给客户端  
  97.                 if (send(new_server_socket, buffer, file_block_length, 0) < 0)  
  98.                 {  
  99.                     printf("Send File:\t%s Failed!\n", file_name);  
  100.                     break;  
  101.                 }  
  102.   
  103.                 bzero(buffer, sizeof(buffer));  
  104.             }  
  105.             fclose(fp);  
  106.             printf("File:\t%s Transfer Finished!\n", file_name);  
  107.         }  
  108.   
  109.         close(new_server_socket);  
  110.     }  
  111.   
  112.     close(server_socket);  
  113.   
  114.     return 0;  
  115. }  
[cpp] view plain copy
  1.   
  2. // file_server.c -- socket文件传输服务器端示例代码  
  3. // /  
  4. #include<netinet/in.h>  
  5. #include<sys/types.h>  
  6. #include<sys/socket.h>  
  7. #include<stdio.h>  
  8. #include<stdlib.h>  
  9. #include<string.h>  
  10.   
  11. #define HELLO_WORLD_SERVER_PORT    6666  
  12. #define LENGTH_OF_LISTEN_QUEUE     20  
  13. #define BUFFER_SIZE                1024  
  14. #define FILE_NAME_MAX_SIZE         512  
  15.   
  16. int main(int argc, char **argv)  
  17. {  
  18.     // set socket's address information  
  19.     // 设置一个socket地址结构server_addr,代表服务器internet的地址和端口  
  20.     struct sockaddr_in   server_addr;  
  21.     bzero(&server_addr, sizeof(server_addr));  
  22.     server_addr.sin_family = AF_INET;  
  23.     server_addr.sin_addr.s_addr = htons(INADDR_ANY);  
  24.     server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);  
  25.   
  26.     // create a stream socket  
  27.     // 创建用于internet的流协议(TCP)socket,用server_socket代表服务器向客户端提供服务的接口  
  28.     int server_socket = socket(PF_INET, SOCK_STREAM, 0);  
  29.     if (server_socket < 0)  
  30.     {  
  31.         printf("Create Socket Failed!\n");  
  32.         exit(1);  
  33.     }  
  34.   
  35.     // 把socket和socket地址结构绑定  
  36.     if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)))  
  37.     {  
  38.         printf("Server Bind Port: %d Failed!\n", HELLO_WORLD_SERVER_PORT);  
  39.         exit(1);  
  40.     }  
  41.   
  42.     // server_socket用于监听  
  43.     if (listen(server_socket, LENGTH_OF_LISTEN_QUEUE))  
  44.     {  
  45.         printf("Server Listen Failed!\n");  
  46.         exit(1);  
  47.     }  
  48.   
  49.     // 服务器端一直运行用以持续为客户端提供服务  
  50.     while(1)  
  51.     {  
  52.         // 定义客户端的socket地址结构client_addr,当收到来自客户端的请求后,调用accept  
  53.         // 接受此请求,同时将client端的地址和端口等信息写入client_addr中  
  54.         struct sockaddr_in client_addr;  
  55.         socklen_t          length = sizeof(client_addr);  
  56.   
  57.         // 接受一个从client端到达server端的连接请求,将客户端的信息保存在client_addr中  
  58.         // 如果没有连接请求,则一直等待直到有连接请求为止,这是accept函数的特性,可以  
  59.         // 用select()来实现超时检测  
  60.         // accpet返回一个新的socket,这个socket用来与此次连接到server的client进行通信  
  61.         // 这里的new_server_socket代表了这个通信通道  
  62.         int new_server_socket = accept(server_socket, (struct sockaddr*)&client_addr, &length);  
  63.         if (new_server_socket < 0)  
  64.         {  
  65.             printf("Server Accept Failed!\n");  
  66.             break;  
  67.         }  
  68.   
  69.         char buffer[BUFFER_SIZE];  
  70.         bzero(buffer, sizeof(buffer));  
  71.         length = recv(new_server_socket, buffer, BUFFER_SIZE, 0);  
  72.         if (length < 0)  
  73.         {  
  74.             printf("Server Recieve Data Failed!\n");  
  75.             break;  
  76.         }  
  77.   
  78.         char file_name[FILE_NAME_MAX_SIZE + 1];  
  79.         bzero(file_name, sizeof(file_name));  
  80.         strncpy(file_name, buffer,  
  81.                 strlen(buffer) > FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE : strlen(buffer));  
  82.   
  83.         FILE *fp = fopen(file_name, "r");  
  84.         if (fp == NULL)  
  85.         {  
  86.             printf("File:\t%s Not Found!\n", file_name);  
  87.         }  
  88.         else  
  89.         {  
  90.             bzero(buffer, BUFFER_SIZE);  
  91.             int file_block_length = 0;  
  92.             while( (file_block_length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)  
  93.             {  
  94.                 printf("file_block_length = %d\n", file_block_length);  
  95.   
  96.                 // 发送buffer中的字符串到new_server_socket,实际上就是发送给客户端  
  97.                 if (send(new_server_socket, buffer, file_block_length, 0) < 0)  
  98.                 {  
  99.                     printf("Send File:\t%s Failed!\n", file_name);  
  100.                     break;  
  101.                 }  
  102.   
  103.                 bzero(buffer, sizeof(buffer));  
  104.             }  
  105.             fclose(fp);  
  106.             printf("File:\t%s Transfer Finished!\n", file_name);  
  107.         }  
  108.   
  109.         close(new_server_socket);  
  110.     }  
  111.   
  112.     close(server_socket);  
  113.   
  114.     return 0;  
  115. }  


 

[cpp] view plaincopyprint?
  1. //  
  2. // file_client.c  socket传输文件的client端示例程序   
  3. // ///  
  4. #include<netinet/in.h>                         // for sockaddr_in  
  5. #include<sys/types.h>                          // for socket  
  6. #include<sys/socket.h>                         // for socket  
  7. #include<stdio.h>                              // for printf  
  8. #include<stdlib.h>                             // for exit  
  9. #include<string.h>                             // for bzero  
  10.   
  11. #define HELLO_WORLD_SERVER_PORT       6666  
  12. #define BUFFER_SIZE                   1024  
  13. #define FILE_NAME_MAX_SIZE            512  
  14.   
  15. int main(int argc, char **argv)  
  16. {  
  17.     if (argc != 2)  
  18.     {  
  19.         printf("Usage: ./%s ServerIPAddress\n", argv[0]);  
  20.         exit(1);  
  21.     }  
  22.   
  23.     // 设置一个socket地址结构client_addr, 代表客户机的internet地址和端口  
  24.     struct sockaddr_in client_addr;  
  25.     bzero(&client_addr, sizeof(client_addr));  
  26.     client_addr.sin_family = AF_INET; // internet协议族  
  27.     client_addr.sin_addr.s_addr = htons(INADDR_ANY); // INADDR_ANY表示自动获取本机地址  
  28.     client_addr.sin_port = htons(0); // auto allocated, 让系统自动分配一个空闲端口  
  29.   
  30.     // 创建用于internet的流协议(TCP)类型socket,用client_socket代表客户端socket  
  31.     int client_socket = socket(AF_INET, SOCK_STREAM, 0);  
  32.     if (client_socket < 0)  
  33.     {  
  34.         printf("Create Socket Failed!\n");  
  35.         exit(1);  
  36.     }  
  37.   
  38.     // 把客户端的socket和客户端的socket地址结构绑定   
  39.     if (bind(client_socket, (struct sockaddr*)&client_addr, sizeof(client_addr)))  
  40.     {  
  41.         printf("Client Bind Port Failed!\n");  
  42.         exit(1);  
  43.     }  
  44.   
  45.     // 设置一个socket地址结构server_addr,代表服务器的internet地址和端口  
  46.     struct sockaddr_in  server_addr;  
  47.     bzero(&server_addr, sizeof(server_addr));  
  48.     server_addr.sin_family = AF_INET;  
  49.   
  50.     // 服务器的IP地址来自程序的参数   
  51.     if (inet_aton(argv[1], &server_addr.sin_addr) == 0)  
  52.     {  
  53.         printf("Server IP Address Error!\n");  
  54.         exit(1);  
  55.     }  
  56.   
  57.     server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);  
  58.     socklen_t server_addr_length = sizeof(server_addr);  
  59.   
  60.     // 向服务器发起连接请求,连接成功后client_socket代表客户端和服务器端的一个socket连接  
  61.     if (connect(client_socket, (struct sockaddr*)&server_addr, server_addr_length) < 0)  
  62.     {  
  63.         printf("Can Not Connect To %s!\n", argv[1]);  
  64.         exit(1);  
  65.     }  
  66.   
  67.     char file_name[FILE_NAME_MAX_SIZE + 1];  
  68.     bzero(file_name, sizeof(file_name));  
  69.     printf("Please Input File Name On Server.\t");  
  70.     scanf("%s", file_name);  
  71.   
  72.     char buffer[BUFFER_SIZE];  
  73.     bzero(buffer, sizeof(buffer));  
  74.     strncpy(buffer, file_name, strlen(file_name) > BUFFER_SIZE ? BUFFER_SIZE : strlen(file_name));  
  75.     // 向服务器发送buffer中的数据,此时buffer中存放的是客户端需要接收的文件的名字  
  76.     send(client_socket, buffer, BUFFER_SIZE, 0);  
  77.   
  78.     FILE *fp = fopen(file_name, "w");  
  79.     if (fp == NULL)  
  80.     {  
  81.         printf("File:\t%s Can Not Open To Write!\n", file_name);  
  82.         exit(1);  
  83.     }  
  84.   
  85.     // 从服务器端接收数据到buffer中   
  86.     bzero(buffer, sizeof(buffer));  
  87.     int length = 0;  
  88.     while(length = recv(client_socket, buffer, BUFFER_SIZE, 0))  
  89.     {  
  90.         if (length < 0)  
  91.         {  
  92.             printf("Recieve Data From Server %s Failed!\n", argv[1]);  
  93.             break;  
  94.         }  
  95.   
  96.         int write_length = fwrite(buffer, sizeof(char), length, fp);  
  97.         if (write_length < length)  
  98.         {  
  99.             printf("File:\t%s Write Failed!\n", file_name);  
  100.             break;  
  101.         }  
  102.         bzero(buffer, BUFFER_SIZE);  
  103.     }  
  104.   
  105.     printf("Recieve File:\t %s From Server[%s] Finished!\n", file_name, argv[1]);  
  106.   
  107.     // 传输完毕,关闭socket   
  108.     fclose(fp);  
  109.     close(client_socket);  
  110.     return 0;  
  111.   
  112. }  

客户端不一定要bind(),服务端一定要bind(),为什么?不然客户端怎么知道服务器位置(IP+PORT)。 一般客户端不绑定端口,因为客户程序经常开关, 由于一些原因(这里我说不清楚,你碰到了自然理解), 断开时端口很少立刻释放(一般要1、2分钟)。 所以客户端绑定端口容易出问题。 
注:服务器绑定的是侦听端口,客户连接后,  新分配一个sock和它连接(这个sock的port是不同的,相当于没有bind的一个端口)  由于侦听端口是没有实际联接的,所以断开时不需握手,也就没有释放问题了。   (注这段是回答时突然想到的,自我感觉是正确的,大家来批判啊)


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384311.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

操作系统(二)进程管理

ui 操作系统&#xff08;二&#xff09;进程管理一、进程程序和进程进程控制块&#xff08;PCB&#xff09;进程的组成进程的特征进程的状态与转换进程状态的转换进程的组织链接方式索引方式进程的控制进程的创建进程的终止进程阻塞进程唤醒进程切换进程通信共享存储消息传递管…

gethostbyname()函数说明

转载&#xff1a;http://www.cnblogs.com/cxz2009/archive/2010/11/19/1881611.html gethostbyname()函数说明——用域名或主机名获取IP地址 包含头文件 #include <netdb.h> #include <sys/socket.h> 函数原型 struct hostent *gethostbyna…

操作系统(三)内存管理

操作系统&#xff08;三&#xff09;内存管理一、程序执行过程装入的三种方式链接的三种方式二、内存管理的概念内存空间的分配与回收连续分配管理方式单一连续分配固定分区分配动态分区分配首次适应算法最佳适应算法最坏适应算法邻近适应算法非连续分配管理方式基本分页存储管…

操作系统(四)文件管理

操作系统&#xff08;四&#xff09;文件管理一、文件系统基础1.文件逻辑结构无结构文件有结构文件2.文件目录文件控制块&#xff08;FCB&#xff09;目录结构单级目录两级目录结构多级目录结构无环图目录结构3.文件保护口令保护加密保护访问控制4.文件共享硬链接软链接5.文件系…

struct stat结构体简介

转载&#xff1a;http://www.cnblogs.com/CSU-PL/archive/2013/06/06/3120757.html 在使用这个结构体和方法时&#xff0c;需要引入&#xff1a; <sys/types.h> <sys/stat.h> struct stat这个结构体是用来描述一个linux系统文件系统中的文件属性的结构。 可以有两种…

如何在Ubuntu上安装GCC编译器

如何在Ubuntu上安装GCC编译器1.首先更新包列表sudo apt update2.安装build-essential软件包&#xff1a; sudo apt install build-essential3.验证GCC编译器是否已成功安装&#xff0c;请使用gcc --version命令打印GCC版本 rootubuntu:/home/csd# gcc --version

操作系统(五)输入/输出(I/O)管理

操作系统&#xff08;五&#xff09;输入/输出&#xff08;I/O&#xff09;管理一、I/O控制器二、I/O控制方式程序直接控制方式中断驱动方式DMA方式通道控制方式I/O软件层次结构假脱机技术设备的分配与回收缓冲区单缓冲双缓冲循环缓冲区缓冲池一、I/O控制器 I/O设备由机械部件…

Linux下的I/O多路复用select,poll,epoll浅析

转载&#xff1a;http://blog.csdn.net/u011573853/article/details/52105365 一&#xff0c;什么是I/O多路复用 所谓的I/O多路复用在英文中其实叫 I/O multiplexing. 就是单个线程&#xff0c;通过记录跟踪每个I/O流(sock)的状态&#xff0c;来同时管理多个I/O流 。) I/O mu…

计算机组成原理(一)计算机系统概述

计算机组成原理&#xff08;一&#xff09;计算机系统概述一、计算机系统层次结构冯诺伊曼机计算机工作过程多级层次结构一、计算机系统层次结构 冯诺伊曼机 特点&#xff1a; 计算机由五大部件组成指令和数据以同等地位存于存储 器&#xff0c;可按地址寻访指令和数据用二进…

计算机组成原理(二)数据的表示和运算

计算机组成原理&#xff08;二&#xff09;数据的表示和运算一、BCD码二、奇偶校验码三、海明码四、循环冗余校验码&#xff08;CRC&#xff09;五、乘法运算原码乘法补码乘法六、除法运算原码除法补码除法七、浮点数的表示与运算浮点数的运算一、BCD码 组合式BCD码&#xff1…

select read write

转载&#xff1a;http://blog.csdn.net/beginning1126/article/details/8057498 [cpp] view plaincopy <p style"color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; "><span style"font-size:14px;…

数据结构(七)图的遍历(递归非递归方法)

图的遍历&#xff08;递归非递归方法&#xff09;#include<iostream> #include<stdio.h> #include<stack> #include<queue> using namespace std;typedef char VertexType; typedef int EdgeType;#define MAXVEX 100 #define INF 65535 bool visited[M…

Linux IO复用区别与epoll详解

转载&#xff1a;http://blog.csdn.net/hacker00011000/article/details/52160590 一、select、poll、epoll之间的区别总结[整理]   select&#xff0c;poll&#xff0c;epoll都是IO多路复用的机制。I/O多路复用就通过一种机制&#xff0c;可以监视多个描述符&#xff0c;一…

简单图和多重图

一、简单图    ① 不存在重复边&#xff1b;    ② 不存在顶点到自身的边&#xff1b; 二、多重图   ① 某两结点之间边数多于一条&#xff1b;   ② 允许顶点通过一条边和自己关联&#xff1b;

C++笔记:select多路复用机制

转载&#xff1a;http://blog.csdn.net/qdx411324962/article/details/42499535 函数作用&#xff1a; 系统提供select函数来实现多路复用输入/输出模型。select系统调用是用来让我们的程序监视多个文件句柄的状态变化的。程序会停在select这里等待&#xff0c;直到被监视的文件…

交叉编译执行应用程序出现:No such file or directory

问题分析 当我在arm板子上执行交叉编译过的程序的时候发现了这个错误。通过百度查询基本都是缺少32位库什么的,但是都不能解决问题。 然后我用ll指令&#xff0c;也排除了权限的原因。 我们用ldd指令发现&#xff0c;它不是动态执行的&#xff0c;虽然我们可以使用-static指…

select、poll、epoll 比较

转载&#xff1a;http://blog.csdn.net/dodo_328/article/details/39081183 1.Selet&#xff1a;本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理。 缺点&#xff1a;1 单个进程可监视的fd数量被限制&#xff0c;因为受描述符集合fd_set限制&#xff0c;fd数量…

C库函数 File

C库函数常用的有&#xff1a;fopen, fclose, fread, fwrite, fgets, fputs, fscanf, fprintf, fseek, fgetc, fputc, ftell, feof, flush等&#xff0c; 当使用fopen打开一个文件时通常返回一个文件指针 FILE *fp。FILE类型是一个结构体&#xff0c;包含文件描述符&#xff08;…

Unix 网络编程(四)- 典型TCP客服服务器程序开发实例及基本套接字API介绍

转载&#xff1a;http://blog.csdn.net/michael_kong_nju/article/details/43457393 写在开头&#xff1a; 在上一节中我们学习了一些基础的用来支持网络编程的API&#xff0c;包括“套接字的地址结构”、“字节排序函数”等。这些API几乎是所有的网络编程中都会使用的一些&…

C库函数与系统函数的关系

转载于:https://www.cnblogs.com/lr1402585172/p/10464933.html