自己編寫的用於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)),則文件雖然也可以傳輸成功,但傳輸的文件可能會出現問題。
代碼比較簡單,有不足之處或可改進的地方,歡迎大家提出意見。