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

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

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

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

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

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

 

直接上源码吧:

 

[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 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. }  


 

  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的一个端口)  由于侦听端口是没有实际联接的,所以断开时不需握手,也就没有释放问题了。   (注这段是回答时突然想到的,自我感觉是正确的,大家来批判啊)


  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值