日期:2014-05-16  浏览次数:20754 次

linuxC socket 发送和接收文件小例子

LINUX C 基于TCP/IP协议的SOCKET收发文件的小例子。

自已没事正看这方面的东西,感觉要想把网络这块弄明白还真不是件简单的事。

程序写的比较繁琐,代码也不合理,有时间再把程序优化一下,加上断点继传的功能。。

服务器端:

/******** http://blog.csdn.net/robertkun ********/
/*******  服务器程序  (server.c)     ************/

// linux 下读取大于2GB文件时,需指定
#define _FILE_OFFSET_BITS 64

#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 <fcntl.h>

// 定义包的大小为512KB
#define PACK_SIZE 1025*512

int main(int argc, char *argv[])
{
	// 设置输出缓冲
	setvbuf(stdout, NULL, _IONBF, 0);
	fflush(stdout);

        int sockfd,new_fd;
        struct sockaddr_in server_addr;
        struct sockaddr_in client_addr;
        int sin_size,portnumber;
        char hello[]="Hello! Are You Fine?\n";

        if((portnumber=atoi("8080"))<0)
        {
                fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]);
                exit(1);
        }

        /* 服务器端开始建立socket描述符 */
        if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) {
                fprintf(stderr,"Socket error:%s\n\a",strerror(errno));
                exit(1);
        }

        /* 服务器端填充 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(1);
        }

        /* 监听sockfd描述符  */
        if(listen(sockfd,5)==-1) {
                fprintf(stderr,"Listen error:%s\n\a",strerror(errno));
                exit(1);
        }

        while(1)
        {
        	fprintf(stderr, "server is listening!\n");

                /* 服务器阻塞,直到客户程序建立连接  */
                sin_size=sizeof(struct sockaddr_in);
                if( ( new_fd = accept(sockfd,(struct sockaddr *)(&client_addr),(socklen_t*)&sin_size ) ) == -1) {
                        fprintf(stderr,"Accept error:%s\n\a",strerror(errno));
                        exit(1);
                }

                fprintf(stderr,"Server get connection from %s\n",
                inet_ntoa(client_addr.sin_addr));
                if(write(new_fd,hello,strlen(hello))==-1) {
                        fprintf(stderr,"Write Error:%s\n",strerror(errno));
                        exit(1);
                }
	
		int read_size = 0;
		unsigned long file_len  = 0;
		int order_id  = 0;
		char file_name[128] = {'\0'};
		char file_info[1024] = {'\0'};
	
		// 读取指令
		if(read(new_fd, file_info, 1024)) {
			// 指令ID
			int id_h = (int)file_info[0]<<8;
			order_id = id_h + (int)file_info[1];

			// 文件长度
			// 高16位
			int len_h_1 = (int)file_info[2]<<8;
			int len_h_2 = len_h_1 + (int)file_info[3];
			int len_h = len_h_2 << 16;

			// 低16位
			int len_l_1 = (int)file_info[4]<<8;
			int len_l = len_l_1 + (int)file_info[5];
			file_len = len_h + len_l;

			// 文件名称
			strncpy(file_name, &file_info[6], strlen(&file_info[6]));

			printf("order = %d, %lu, %s\n", order_id, file_len, file_name);
		}
		else {
			printf("Read file error!\n");
			close(new_fd);
			close(sockfd);
			exit(0);
		}
	
		// 写入文件
		FILE* pf = fopen(file_name, "wb+");
		char buff[PACK_SIZE] = {'\0'};
		while(read_size <= file_len) {
			//bzero(buff, 1024);
			int rlen = read(new_fd, buff, PACK_SIZE);
			if(rlen) {
				system("clear");
				printf("Read package size = %d\n", rlen);
		
				fwrite(buff, sizeof(cha