基於socket網絡編程的文件傳輸程序

自己編寫的用於linux下的簡單文件傳輸程序,,傳輸模式爲二進制,只可用於文件傳輸,分爲客戶端和服務器端,運行時先執行服務器端程序,再執行客戶端程序,注意服務器端和客戶端的文件名要在代碼中修改。運行時直接輸入./server和./client,不需要輸入任何參數。

代碼如下:


服務器端

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include<stdlib.h>
#include<string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define LISTENQ 20
#define PORT 8888
 
int main(int argc, char *argv[])
{

     struct sockaddr_in server_addr;
     struct sockaddr_in client_addr;
        
     int sockfd, acceptfd;
     unsigned char *buffer; 
     socklen_t sin_size;
     int fd, n;     
      
     if(argc!=1)
     {
            fprintf(stderr, "Usage: %sportnumber\a\n", argv[0]);
            exit(1);
     }
 				
       /* 服務器端開始建立 socket 描述符 */
     if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
     {
            fprintf(stderr, "Socketerror:%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(PORT);

			/* 將server_addr結構綁定到sockfd */
	   if(bind(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1)
	   {
		   //fprintf(stderr, "bind error: %s \n", strerror(errno));
		   fprintf(stderr, "bind error: %s\n", strerror(errno));
		   exit(1);
	   }
	   printf("bind port success.\n");

			/* 監聽端口,等待客戶端的連接 */
	   if(listen(sockfd, LISTENQ) == -1)
	   {
		   fprintf(stderr, "listen error: %s \n", strerror(errno));
		   exit(1);
	   }
		 printf("server is listenning...\n");
			
	   sin_size = sizeof(struct sockaddr_in);
	   /* 接受客戶端連接 */
	   if((acceptfd = accept(sockfd, (struct sockaddr *)(&client_addr), &sin_size)) == -1)
	   {
		   fprintf(stderr, "accept error: %s \n", strerror(errno));
		   exit(1);
	   }
		 printf("success accept the link of client.\n");
	
	   
		 //unsigned char *buffer = (unsigned char *)malloc(8192);//2*2048*500); 
		 /* 申請分配8192個字節的內存空間 */
		 buffer = (unsigned char *)malloc(8192); 
		 if(buffer)  
     		printf("Memory Allocated at: %x\n",buffer);  
     else  
     {
     		printf("Not Enough Memory! Malloc error! \n");
        return -1;//goto err_ret;  
     }
	 
	 	 
			//fd = fopen("/home/ddrdate", "wb");
			/* 打開/home下名爲u-boot-xlnx-xilinx-v2014.4.tar.gz的文件(此處實爲創建一個空的文件) */
		 fd = open("/home/test/u-boot-xlnx-xilinx-v2014.4.tar.gz", O_RDWR | O_CREAT); //上位機文件存儲位置
			 printf("fd = %d \n", fd);	   
	   while(1)
	   { 
		   volatile int wr_len;
		   //if(read(acceptfd, buffer, sizeof(buffer)) == -1)
		   /* 從acceptfd讀取數據到buffer中 */
		   if((n = recv(acceptfd, buffer, sizeof(buffer), 0)) == 0) //sizeof(buff), 0) ==0)
		   {
			   printf("read over.\n");//printf(stderr, "read error: %s \n", strerror(errno));
			   break;//exit(1):
		   }    
		   //else
		   	//printf("read date success.\n");

				//if((wr_len = fwrite(buff, sizeof(buff), 1, fd) ==0)
				/* 將數據寫到文件句柄fd中 */
		   if((wr_len = write(fd, buffer, n)) == -1)
		   {
			   fprintf(stderr, "write to /home/ddrdate.bin error: %s \n", strerror(errno));
			   break;//exit(1);
		   }
		   else
			   printf("write data: %d \n", wr_len); 
	   }
	   free(buffer);
	   close(acceptfd);
	   close(sockfd);
	return 0;
}


客戶端

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include<stdlib.h>
#include<string.h>

/* 與服務器端建立連接 */
int CreateSock(char *destip, int port)     /* destip爲服務器端IP,port爲其端口 */               
{                                                                    
                                                                     
	//int port = atoi(destport);                                         
  int connectfd;  
  
  /* 創建套接字,使用TCP協議 */                                                   
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);   
	printf("sockfd=%d\n", sockfd);                     
                                            
  /* 客戶端填充服務器端信息 */                         
	struct sockaddr_in saddr;                                           
	bzero(&saddr, sizeof(struct sockaddr_in));         /* 清空地址結構*/                                    
	saddr.sin_family = AF_INET;                      	 /* 使用IPV4通信域 */
	saddr.sin_port = htons(port);                      /* 端口號轉換爲網絡字節序 */                
	inet_pton(AF_INET,destip,&saddr.sin_addr.s_addr);  /* 將“點分十進制”的IP地址轉換爲“整數” */
   
   /* 主動連接服務器 */                                                              
	if((connectfd = connect(sockfd, (struct sockaddr*)(&saddr), sizeof(saddr)))<0)       
	  {                                                                
			perror("connect");                                             
			printf("connect error! stop send!\n");                         
			exit(1);                                                       
	  }  
	  printf("connectfd=%d\n", connectfd);  
	 //close(sockfd);                                                            
	return sockfd;//connectfd;                                                     
} 

int retr(int connfd)
{
	//int fd;
	FILE *fd;
	int n;
	char buf[BUFSIZ];
	volatile int len;
	//if((fd=open("/home/READ.txt", O_RDWR)) == -1)
	/* 打開/home下的u-boot-xlnx-xilinx-v2014.4.tar.gz文件,返回其句柄 */
	if((fd=fopen("/home/u-boot-xlnx-xilinx-v2014.4.tar.gz", "rb")) == NULL) 
	{
			printf("open file error.\n");
			return -1;
	}
	else
		printf("open file success.\n");
	
	while(1)
	{
		//if(read(fd, buf, sizeof(buf)) == 0)
		/* 從fd讀8192個字節數據到buf中 */
		if((n = fread(buf, 1, 8192, fd)) == 0)  //fd -> buf
		{
			fprintf(stderr,"fread error or over: %s\n", strerror(errno));
			break;
		}
		/*{
			printf("read error or over.\n");
			break;
		}
		*/
		//if((len = write(connfd, buf, sizeof(buf))) == 0)
		printf("connfd=%d\n", connfd);
		/* 將buf中數據發送到連接套接字connfd */
		if((len = send(connfd, buf, n, 0)) == -1)
		{
			fprintf(stderr, "send error: %s\n", strerror(errno));
			break;
		}
		printf("send data: %d \n", len);
	}	
	
	close(connfd);
	fclose(fd);
}

int main()
{
	int connfd;
	connfd = CreateSock("10.8.248.159", 8888);
	printf("main connfd = %d\n", connfd);
	retr(connfd);

	return 0;
}    


這裏要注意的一個地方是,服務器端的程序中write()函數的第三個參數應爲recv的返回值n,若爲其他值如write(fd, buffer, sizeof(buffer)),則文件雖然也可以傳輸成功,但傳輸的文件可能會出現問題。

代碼比較簡單,有不足之處或可改進的地方,歡迎大家提出意見。

發佈了40 篇原創文章 · 獲贊 37 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章