Linux socket文件传输2
来源:互联网 发布:和飞行员谈恋爱 知乎 编辑:程序博客网 时间:2024/06/02 04:35
以下代码是《Linux socket文件传输》的完善版本,主要是添加了命令行参数的设置功能。
1 发送端
/******* 发送端:客户端 sent.c ************/#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <netdb.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/types.h>#include <arpa/inet.h>#include <getopt.h>#include <string.h>#include <stdbool.h>#define MY_NAME "sent"#define CMD_FAILSE 0#define CMD_TURE 1#define CMD_NOFILE 2 // 没有指定要发送的文件static int portnumber = 8888;static char sent_file_name[256];static struct hostent *host;/* * 命令行选项 */static struct option options[] = { {"help",no_argument, 0, 'h' }, {"port", required_argument, 0, 'p' }, {"file", required_argument, 0, 'f' }, {"server", required_argument, 0, 's' }, {0, 0, 0, 0 }};/* * 命令行选项说明 */static const char *options_descriptions[] = {"Show this help and quit.","Set port number.","Send file name.","Set server ip.",};/* * 功 能:显示程序的帮助信息 */static void usage(void){unsigned int i;printf("Usage:\n\t" MY_NAME " -f <filename> [-p <port>]""\n\nOptions:\n");for (i = 0; options[i].name; i++)printf("\t-%c, --%s\n\t\t\t%s\n",options[i].val, options[i].name,options_descriptions[i]);}/* * 功 能: 解析程序参数 * 参 数: 同main()的参数 * 返 回: true —— 参数非法,或者是--help * false —— 参数合法,且不是--help */static int cmd_arg_parse( int argc, char **argv ){int opt, option_index = 0;int ret = CMD_NOFILE;while ( ( opt = getopt_long(argc, argv, "p:f:s:h",options, &option_index)) != -1) { switch ( opt ) { case 'p': if (optarg)if( ( portnumber = atoi( optarg )) < 0 ){fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]);return CMD_FAILSE;} break; case 'f': if (optarg) {strcpy(sent_file_name, optarg);ret = CMD_TURE;} break; case 's':if (optarg) {if( ( host = gethostbyname( optarg ) ) == NULL) { fprintf(stderr, "Gethostname error\n"); return CMD_FAILSE;}}break; case 'h': // 显示帮助信息usage();break; default: printf("?? getopt returned character code 0%o ??\n", opt); break; } } if ( optind < argc ) { printf("non-option ARGV-elements: "); while ( optind < argc ) printf( "%s ", argv[optind++] ); printf("\n"); } return ret;}/* * 提示当前的参数设置 */static void hints(void){printf("port number : %d\n", portnumber);printf("file name : %s\n", sent_file_name);}int main(int argc, char *argv[]){int sockfd = -1;int exit_code = 0;struct sockaddr_in server_addr;switch ( cmd_arg_parse(argc, argv) ) {case CMD_NOFILE:fprintf(stderr, "Error: You must specified a file name !\n");case CMD_FAILSE:return -1;}hints();FILE *fp = fopen( sent_file_name, "rb" );if ( fp == NULL) {fprintf(stderr, "Open file error\n");exit_code = 1;goto FINISHED;}/* 客户程序开始建立 sockfd描述符 */if( ( sockfd = socket( AF_INET,SOCK_STREAM, 0 ) ) == -1) {fprintf( stderr, "Socket Error:%s\a\n", strerror(errno) );exit_code = 1;goto FINISHED;}/* 客户程序填充服务端的资料 */bzero( &server_addr, sizeof( server_addr ) );server_addr.sin_family = AF_INET;server_addr.sin_port = htons( portnumber );server_addr.sin_addr = *( ( struct in_addr * )host->h_addr );/* 客户程序发起连接请求 */ if( connect( sockfd, ( struct sockaddr * )( &server_addr ), sizeof( struct sockaddr ) ) ==-1 ) {fprintf(stderr, "Connect Error:%s\a\n", strerror(errno));exit_code = 1;goto FINISHED;}size_t nreads, nwrites;char buffer[1024];while( nreads = fread( buffer, sizeof(char), sizeof( buffer ), fp) ) {if ( ( nwrites = write( sockfd, buffer , nreads) ) != nreads ) {fprintf(stderr, "write error\n");exit_code = 1;goto FINISHED;}}/* 结束通讯 */FINISHED:if ( fp != NULL )fclose( fp );if ( sockfd != -1)close( sockfd );exit( exit_code );}
说明:sent --help可以查看帮助说明
2 接收端/******* 文件接收端:服务器(recv.c) ************/#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <netdb.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/types.h>#include <arpa/inet.h>#include <sys/socket.h>#include <netinet/tcp.h>#include <stdbool.h>#include <getopt.h>#include <string.h>#define MY_NAME "recv"static int portnumber = 8888;static char save_file_name[256] = "out.txt";/* * 命令行选项 */static struct option options[] = { {"help",no_argument, 0, 'h' }, {"port", required_argument, 0, 'p' }, {"f", required_argument, 0, 'f' }, {0, 0, 0, 0 }};/* * 命令行选项说明 */static const char *options_descriptions[] = {"Show this help and quit.","Set port number.","Set output file name.",};/* * 功 能:显示程序的帮助信息 */static void usage(void){unsigned int i;printf("Usage:\n\t" MY_NAME " [-f <filename>] [-p <port>]""\n\nOptions:\n");for (i = 0; options[i].name; i++)printf("\t-%c, --%s\n\t\t\t%s\n",options[i].val, options[i].name,options_descriptions[i]);}/* * 功 能: 解析程序参数 * 参 数: 同main()的参数 * 返 回: true —— 参数非法,或者是--help * false —— 参数合法,且不是--help */static bool cmd_arg_parse( int argc, char **argv ){int opt, option_index = 0;;int ret = true;while ( (opt = getopt_long(argc, argv, "p:f:h",options, &option_index)) != -1) { switch ( opt ) { case 'p': if (optarg)if( ( portnumber = atoi( optarg )) < 0 ){fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]);return false;} break; case 'f': if (optarg)strcpy(save_file_name, optarg); break; case 'h': // 显示帮助信息usage();ret = false;break; default: printf("?? getopt returned character code 0%o ??\n", opt); ret = false; break; } } if ( optind < argc ) { printf("non-option ARGV-elements: "); while ( optind < argc ) printf( "%s ", argv[optind++] ); printf("\n"); ret = false; } return ret;}/* * 提示当前的参数设置 */static void hints(void){printf("port number : %d\n", portnumber);printf("file name : %s\n", save_file_name);}int main(int argc, char *argv[]){int sockfd = -1;int exit_code = 0;struct sockaddr_in server_addr;struct sockaddr_in client_addr;// 命令行参数分析if ( !cmd_arg_parse(argc, argv) )return -1;// 提示hints();/* 服务器端开始建立socket描述符 */if( ( sockfd = socket( AF_INET, SOCK_STREAM, 0) ) == -1 ) {fprintf(stderr,"Socket error:%s\n\a",strerror(errno));exit_code = 1;goto FINISHED;}/* 服务器端填充sockaddr结构 */ bzero( &server_addr, sizeof(struct sockaddr_in) );server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = htonl( INADDR_ANY );server_addr.sin_port = htons( portnumber );/* 捆绑sockfd描述符 */ if( bind( sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr))==-1) {fprintf( stderr, "Bind error:%s\n\a", strerror( errno ) );exit_code = 1;goto FINISHED;}/* 监听sockfd描述符 */if( listen(sockfd, 5) == -1) {fprintf( stderr, "Listen error:%s\n\a", strerror( errno ) );exit_code = 1;goto FINISHED;}while( 1 ){/* 服务器阻塞,直到客户程序建立连接 */int sin_size = sizeof(struct sockaddr_in);int new_fd = accept( sockfd, (struct sockaddr *)(&client_addr), &sin_size );if( new_fd == -1 ) {fprintf(stderr,"Accept error:%s\n\a", strerror( errno ) );exit_code = 1;goto FINISHED;}printf("Server get connection from %s\n",inet_ntoa( client_addr.sin_addr ) ); bool tcp_established = true;FILE *save_fp = fopen(save_file_name, "w");if ( save_fp == NULL) {exit_code = 1;goto FINISHED;}while( tcp_established ) {struct tcp_info info; int len = sizeof(info);getsockopt( new_fd, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len ); if( info.tcpi_state == TCP_ESTABLISHED ) { // TCP连接还没有中断,可以读数据char buffer[1024];ssize_t length = read( new_fd, buffer, sizeof(buffer) ); if( length == -1 ) {fprintf(stderr, "Read Error:%s\n", strerror( errno ));exit_code = 1;goto FINISHED;}else if ( length > 0){fwrite(buffer, sizeof(char), length, save_fp);}}else {tcp_established = false;fclose( save_fp );printf("received finished !\n");}}/* 这个通讯已经结束 */close( new_fd );/* 循环下一个 */ }FINISHED:if ( sockfd != -1)close( sockfd );exit( exit_code );}说明:recv --help可以查看帮助说明
0 0
- Linux socket文件传输2
- linux socket 文件传输程序
- Linux socket文件传输
- Linux下的socket文件传输
- Linux网络编程:socket文件传输
- linux下的TCP/IP socket 文件传输
- linux下的TCP/IP socket 文件传输
- Linux下的TCP/IP socket 文件传输
- Linux下的TCP/IP socket 文件传输
- Linux网络编程:socket文件传输范例
- Linux socket编程(五) 文件传输
- Linux socket跨局域网聊天和文件传输
- Linux网络编程之socket文件传输示例
- Linux下C语言Socket实现文件传输
- Linux socket编程(五) 文件传输
- Linux网络编程之socket文件传输示例
- Linux网络编程之socket文件传输示例
- Linux网络编程之socket文件传输示例
- 实验--多线程
- 浅谈 JavaScript 编程语言的编码规范
- 点击精灵区域消除,点击其他区域创建新精灵。(模拟放置炸弹,及引爆)
- Android利用canvas画各种图形(点、直线、弧、圆、椭圆、文字、矩形、多边形、曲线、圆角矩形)
- Linux SSH远程文件/目录传输命令scp
- Linux socket文件传输2
- 黑马程序员---Java 正则表达式
- iOS之数据请求NSURLConnection
- dubbo2.5.3 dubbo:application
- Linux权限管理——sudo和chattr权限
- 装饰者模式及C++ 2
- leetcode--Path Sum
- Java Word 转 Pdf
- 使用URL Rewrite 实现网站伪静态