文档库 最新最全的文档下载
当前位置:文档库 › Linux下基于socket的文件传输程序设计

Linux下基于socket的文件传输程序设计

Linux下基于socket的文件传输程序设计
Linux下基于socket的文件传输程序设计

课程设计

课程名称Linux下基于socket的文件传输程序设计学生学院信息工程学院

专业班级

学号

学生姓名

指导教师

2013 年12月27日

引言

在互联网已经基本普及的情况下,人们越来越依赖于信息网络。因为互联网的使用,我们可以大大的节省了我们的时间及成本。所以文件、信息的传输已经是人们生活中不可缺少的东西。而现在主流的应用软件都是基于WINDOWS平台上开发运行的。

Linux操作系统本身具有非常高的安全性,不易感染病毒(这是WINDOWS系统所不能比拟的),而且可移植性强,应用于大多数的服务器。所以我们应该多开发出适合人们使用的应用软件,使得Linux更加好的为广大网民使用以保障自身的安全性。

本课设主要介绍在Linux下的文件传输原理及功能,虽然不能与主流传输软件的功能相比,但是却是占用的资源比它要少

·1课设背景分析

这次课程设计的要求是在以Linux为内核的操作系统下,实现多线程文件传输系统功能模块。系统模块分为服务器和客户端两部分,客户端实现对文件的上传、下载和查看服务器默认路径下的文件列表;服务器可以对文件进行管理操作,包括创建、删除和重命名等。

多线程文件传输是一种一对多或者多对多的关系,一般是一个服务器对应着多个客户端。客户端通过socket连接服务器,服务器要为客户端创建一个单独进程(线程)监听每个客户端的请求。

创建好连接之后文件就可以通过流的形式传输。linux内核中为我们提供了两种不同形式的读写流,包括read()、write()和send()、recv()。客户机对文件的查看指令也是通过流传递给服务器,服务器根据请求类型返回不同相应流。

根据socket原理和特点绘画出链接流程图,将客户机与服务器的相互通信划分为不同的模块,每个模块负责独立的功能项。服务器输入指令管理目录下的文件,create filename是创建文件命令,rename oldname newname是删除文命令,delete filename 是删除文件命令,同时监听着客户端的请求;客户端向服务器发送上传、下载和查看请求,从而得到不同的相应,包括将文件下载到当前路径下,从当前路径下上传文件给服务器,列出服务器的文件列表。

·2网络通信原理及socket简介

2.1网络通信原理(TCP)

国际标准化组织(ISO)在1978年提出开放系统互连参考模型(OSI:open system interconnection reference mode),该模型是设计和描述网络通信的基本框架。OSI采用分层的额结构化技术将通信网络分为7层,从低到高为物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。

TCP/IP参考模型是由美国国防部创建,且发展至今最成功的通信协议模型,与OSI模型对应,它将网络功能分为4层,包括网络接口层、网络层、传输层和应用层,每一层都有对应的协议。在传输层的主要协议是TCP协议和UDP协议。socket连接就是基于TCP协议。TCP是一种可靠地数据传输协议。

它为应用程序提供可靠的通信连接。适合于一次传输大批数据的情况。并适用于要求得到响应的应用程序并通过3次握手。

其数据包头格式为:

ACK K+1

2.2 socket 简介

在Linux 中的网络编程是通过socket 接口来进行的。socket 是一种特殊的I/O 接口,它也是一种文件描述符。它是一种常用的进程之间通信机制,通过它不仅能实现本地机器上的进程之间的通信,而且通过网络能够在不同机器上的进程之间进行通信。

每一个socket 都用一个半相关描述{协议、本地地址、本地端口}来表示;一个完整的套接字则用一个相关描述{协议、本地地址、本地端口、远程地址、远程端口}来表示。socket 也有一个类似于打开文件的函数调用,该函数返回一个整型的socket 描述符,随后的连接建立、数据传输等操作都是通过socket 来实现的。

socket 是一种套接口,它把网络地址和端口号信息放在一个结构体中,也就是套接字地址结构。

结构图如下:

通用套接口地址数据结构定义在头文件中,形式如下: struct sockaddr

套接口与ip 、端口号的关系 套接口 168.222.222.222 9999

222.222.222.222 9999

Ip 地址

端口号

{

uint8_t sa_len;

sa_family_t sa_family;

char sa_data[14];

};

IPv4套接口地址数据结构以socketaddr_in 命名,定义在头文件中,形式如下:

struct socketaddr_in

{

unit8_t sin_len;

sa_family_t sin_family;

in_port_t sin_port;

struct in_addr sin_addr;

unsigned char sin_zero[8];

}

下图是TCP 套接口通信工作流程图:

通信工作的大致流程:

1) 服务器先用socket()函数来建立一个套接口,用这个套接口完成通信的

监听及数据的收发。

2)服务器用bind()函数来绑定一个端口号和ip地址,是套接口与指定的端口号和ip关联。

3)服务器调用linsten()函数,是服务器的端口和Ip处于监听状态,等待网络中某一个客户机的连接请求。

4)客户机用socket()函数建立一个套接口,设定远程ip和端口

5)客户机调用connect()函数连接远程计算机指定的端口。

6)服务器调用accept()函数来接受远程计算机的连接请求,建立起与客户机之间的通信连接。

7)建立连接之后,客户机用write()函数(或send())想socket中写入数据。也可以用read()函数(或recv()函数)赌气服务器发送来的数据。

8)服务器用read()函数(或recv()函数)来读取客户机发来的数据,也可以用write()函数(或send()函数)来发送数据。

9)完成通信以后,使用close()函数关闭socket连接。

·3详细设计过程

·3.1服务器端创建监听与文件管理

服务器负责的功能模块主要有两部分,一是对连接进来客户端所有线程的管理和服务器目录下的文件管理;二是创建线程来单独监听客户端的动作。为了便于管理,我们创建两个user.txt和client.txt两个文档来分别负责服务器的连接和客户端的连接。user.txt中存放了服务器名和密码。client.txt存放了连接客户端名字和密码。

我们首先对服务器的创建有个监测,即在启动时先核实服务器的所有者username和密码password,将输入的用户、密码与user.txt中的用户密码比较,匹配成功则同意启动,否则return -1表失败。

接着创建一个socket套接口,绑定Ip设置客户端的最大连接数为10,然后创建一个sever线程来实现对服务器本身监听动作。主体代码见最后接下来创建线程完成对客户端的监听

监听等待连接:

while(1)

{

sockdata = accept(sockfd,(struct sockaddr*)0,(int*)0);

…………….

我们定义结构体:

struct client_t

{

pthread_t tid;

int conn_fd;

int used;

char name[20];

}p_client[10];

来存放每个客户端的socket信息、线程标识、使用号、连接号和客户名。创建线程实现单独监听:

p_client[i].conn_fd = sockdata;

p_client[i].used = i;

strcpy(p_client[i].name , client_name);

pthread_create(&p_client[i].tid,NULL,&client_conn,&p_client[i])

接下来是线程client_conn()的功能

监听客户端的功能完成。

·3.2客户端连接与文件传输

在客户端这边我们同样适用了检测机制,运行客户机时要将用户名、密码以及ip地址和端口号作为参数输进来,先建立与服务器的连接,然后将用户名和密码发送到服务端检测,如果检测失败则接收到一条拒绝信息,连接断开,如果检测成功则接收到一条确认信息,双方通信开始。

主体代码见最后:

到此为止我们已经实现了服务器和客户端的主体功能,具体代码查看附录文件夹。

具体代码如下:

服务端:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define MAXBUF 256

/*-------start of fileList functions----------*/ int fileSize(char fileName[]);

//文件信息

typedef struct fileinfo{

char name[256];

char fullName[1024];

int size;

time_t mod_time;

char type[10];

}fileinfo;

//文件列表

typedef struct filelist

{

fileinfo file;

struct filelist* nextfile;

}fileList;

//function getfilelist

//输入目录名

//输出目录下的文件列表头指针

fileList * getFileList(char name[1024])

{

fileList *head=NULL;

fileList *cur=NULL;

char name_temp[1024];

//目录

DIR * dir;

//目录环境

struct dirent *dir_env;

//文件描述

struct stat stat_file;

//初始化head

head =(fileList*)malloc(sizeof(fileList)); head->nextfile = NULL;

//打开目录

dir=opendir(name);

while(dir_env=readdir(dir))//读文件描述表

{

//排除.和..

if(strcmp(dir_env->d_name,".")==0 || strcmp(dir_env->d_name,"..")==0)

continue;

//把文件全名保存到新变量

strcpy(name_temp,name);

strcat(name_temp,dir_env->d_name);

stat(name_temp,&stat_file);//获取文件描述信息

//将文件信息存放到链表中

//产生临时节点

cur=(fileList*)malloc(sizeof(fileList));

//cur赋值

//文件名,fullName=cur_dir+"name";

strcpy(cur->https://www.wendangku.net/doc/c83399777.html,,dir_env->d_name);

strcpy(cur->file.fullName,name_temp);

//文件大小

//文件类型

if( S_ISDIR(stat_file.st_mode))

{

cur->file.size = 0;

strcpy(cur->file.type,"mulu");

strcat(cur->file.fullName,"/");

}else

{

cur->file.size = stat_file.st_size;

strcpy(cur->file.type,"file");

}

//修改日期

cur->file.mod_time = ctime(&stat_file.st_mtime);

//将临时节点插入head中

if(head->nextfile ==NULL)

{

head->nextfile = cur;

cur->nextfile = NULL;

}else

{

cur->nextfile = head->nextfile;

head->nextfile = cur;

}

}

return head;

}

//showAllNode

//输入:目录

//输出:次目录下所有的文件,和所有目录之下的文件

void showAllNode(fileList *head)

{

fileList * temp;

//数组索引

int i=0,j=0;

//如果head为空,直接返回

fileList * headArray[1024];

if(head == NULL)

return ;

//输出当前目录

printf("%s ",head->file.fullName);

printf("\n");

//输出head中的文件

temp =head->nextfile;

char fileListString[MAXBUF];

FILE *file;

char _temp[30];

strcpy(_temp,"temp.txt");

file=fopen(_temp,"w");

if(file==NULL){

printf("The file is created failed!");

exit(1);

}

while(temp)

{

//判断是否为文件,是文件显示文件

//若为目录,将目录名放入队列,求队列目录

if (strcmp(temp->file.type,"file")==0)

{

bzero(fileListString,MAXBUF);

printf("file:%s ",temp->file.fullName);

strcat(fileListString,temp->file.fullName);

strcat(fileListString,"\n");

while ((strlen(fileListString)) > 0)

{

int write_length = fwrite(fileListString, sizeof(char), strlen(fileListString), file);

if (write_length < strlen(fileListString))

{

printf("File Write into Failed\n");

break;

}

bzero(fileListString, MAXBUF);

}

}else{

if(i>=1024)

{

printf("there are too many direcotry\n");

return;

}

//头节点初始化

headArray[i] = getFileList(temp->file.fullName);

//头节点名称

strcpy(headArray[i]->file.fullName,temp->file.fullName); i++;

}

temp=temp->nextfile;

}

fclose(file);

//对目录队列中目录使用递归,直到结束

for(j=0;j

showAllNode(headArray[j]);

return ;

}

//showList

//输入:列表头

//输出:显示列表,返回void

void showList(fileList * head)

{

//判断head 是否为空,若为空直接返回

if(head == NULL)return;

//若不为空则显示它的内容

while(head)

{

printf("%s\n",head->file.fullName);

head = head->nextfile;

}

return ;

}

/*----------end of fileList functions-----------*/

void main()

{

int opt=1;

while(opt!=0){

printf("Please choose your choice bellow:\n");

printf("1:Manage the files.\n");

printf("2:Connect the clients.\n");

char window[2];

scanf("%s",window);

if((strncmp(window,"1",1))==0){

printf("Please input your choice bellow:\n");

printf("1: Create a new file.\n");

printf("2: Delete a file.\n");

printf("3: Rename a known file.\n");

char choice[2];

scanf("%s",choice);

if((strncmp(choice,"1",1))==0){

printf("Please input the new file name:");

char filename[20];

scanf("%s",filename);

FILE *file;

file=fopen(filename,"w");

if(file==NULL){

printf("The file created failed!\n");

}

else{

printf("The file has created successfully.\n");

}

continue;

}

else if((strncmp(choice,"2",1))==0){

printf("Please input the file name with the file path you want to delete:\n");

char filename[20];

scanf("%s",filename);

remove(filename);

printf("The file has been deleted successfully.\n");

continue;

}

else{

printf("Please input the file name you want to rename:\n");

char _old[20];

scanf("%s",_old);

printf("Please input the new file name:\n");

char _new[20];

scanf("%s",_new);

int result = rename( _old, _new );

if( result != 0 )

printf( "Could not rename '%s'\n", _old );

else

printf( "File '%s' renamed to '%s'\n", _old, _new );

continue;

}

}

else{

int ssock;

int clen;

struct sockaddr_in client_addr,server_addr;

char buf[MAXBUF];

if((ssock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))<0){ perror("socket error:");

exit(1);

}

printf("Run the server successfully.\nAnd now waiting the client comming...\n");

memset(&server_addr,0,sizeof(server_addr));

server_addr.sin_family=AF_INET;

server_addr.sin_addr.s_addr=inet_addr("127.0.0.1");

server_addr.sin_port=htons(6669);

if(bind(ssock,(struct sockaddr *)&server_addr,sizeof(server_addr))<0){

perror("bind error:");

exit(1);

}

int window=1;

while(window!=0){

clen=sizeof(client_addr);

recvfrom(ssock,(void *)buf,MAXBUF,0,(struct sockaddr*)&client_addr,&clen);

printf("%s\n",buf);

if((strncmp(buf, "0", 1)) == 0)

{

if((strncmp(buf, "0yy", 7)) == 0)

{

strcpy(buf,"yes");

printf("It's username and right.\n");

}

else

{

strcpy(buf,"no");

printf("It's username but wrong.\n");

}

sendto(ssock,(void *)buf,MAXBUF,0,(struct sockaddr*)&client_addr ,sizeof(client_addr));

}

else if((strncmp(buf, "1", 1)) == 0)

{

if((strncmp(buf, "1123", 4)) == 0)

{

strcpy(buf,"yes");

sendto(ssock,(void *)buf,MAXBUF,0,(struct sockaddr*)&client_addr ,sizeof(client_addr));

printf("It's password and right.\n");

recvfrom(ssock,(void *)buf,MAXBUF,0,(struct sockaddr*)&client_addr,&clen);

if((strncmp(buf, "upload", 5)) == 0){

printf("The client is going to upload file...\n");

recvfrom(ssock,(void *)buf,MAXBUF,0,(struct sockaddr*)&client_addr,&clen);//get filename

printf("The filename of the file uploaded by user is:%s\n",buf);

FILE *file;

char temp[30];

strcpy(temp,"recieve/");

strcat(temp,buf);

file=fopen(temp,"w");

if(file==NULL){

printf("The file is created failed!");

exit(1);

}

bzero(buf, MAXBUF);

recvfrom(ssock,(void *)buf,MAXBUF,0,(struct sockaddr*)&client_addr,&clen);

while (strlen(buf) > 0)

{

int write_length = fwrite(buf, sizeof(char), strlen(buf), file);

if (write_length < strlen(buf))

{

printf("File Write into Failed\n");

break;

}

bzero(buf, MAXBUF);

}

fclose(file);

printf("Recieve file already success.\n");

}

else{

printf("The client wants to download file.\n");

printf("Send the filelist to the client...\n");

//filelist

fileList *mylist;

//显示的目录

char name[1024]="recieve/";

//取得目录下文件

//头指针传递的目录或者文件名

mylist =getFileList(name);

strcpy(mylist->file.fullName,name);

//显示目录下文件

//showList(mylist);

//显示目录下所有文件

showAllNode(mylist);

//send fileList

FILE *file;

char temp[30];

strcpy(temp,"temp.txt");

file=fopen(temp,"r");

if(file==NULL){

printf("The file cannot open!");

exit(1);

}

else{

printf("\nThe fileListString open successfully!\n");

bzero(buf,MAXBUF);

int lengsize = 0;

while((lengsize = fread(buf,1,MAXBUF,file)) > 0)

{

printf("lengsize = %d\n",lengsize);

sendto(ssock,(void

*)buf,MAXBUF,0,(struct sockaddr*)&client_addr,sizeof(server_addr));

printf("%s\n",buf);

bzero(buf, MAXBUF);

}

printf("The fileListString has been sent to the client already.\n");

}

fclose(file);

bzero(buf, MAXBUF);

recvfrom(ssock,(void *)buf,MAXBUF,0,(struct sockaddr*)&client_addr,&clen);

printf("The client choosen file: %s\n",buf);

strcpy(temp,"recieve/");

strcat(temp,buf);

file=fopen(temp,"r");

if(file==NULL){

printf("The file is created failed!");

exit(1);

}

else{

printf("The file open successfully!\n");

printf("The file is downloading to the client now...\n");

bzero(buf,MAXBUF);

int lengsize = 0;

while((lengsize = fread(buf,1,MAXBUF,file)) > 0)

{

printf("lengsize = %d\n",lengsize);

sendto(ssock,(void

*)buf,MAXBUF,0,(struct sockaddr*)&client_addr,sizeof(server_addr));

bzero(buf, MAXBUF);

}

printf("The file has been downloaded already.\n");

}

fclose(file);

exit(1);//还可以显示此时的文件目录信息,检查是否完成了上传

}

close(ssock);

window=0;

}

else

{

strcpy(buf,"no");

sendto(ssock,(void *)buf,MAXBUF,0,(struct sockaddr*)&client_addr ,sizeof(client_addr));

printf("It's password but wrong.\n");

}

}

}

}

}

}

客服端:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define PORT 6669

#define MAXBUF 256

int check_passwd(int sockfd);

int tra_file(int sockfd);

void main ( int argc, char *argv[])

{

char username[20];

char password[20];

char temp[21];

char window;

printf("Please input your selections bellow:\n");

printf("1:Login the server with your username and password\n");

printf("2:Registe a newly user now.\n");

printf("0:Exit the system.\n");

window=getchar();

while(window>0){

if(window=='1'){

int key=0;

printf("Please input your username:");

scanf("%s",username);

printf("%s\n",username);

int ssock;

int clen;

struct sockaddr_in client_addr,server_addr;

char buf[MAXBUF];

if((ssock = socket(AF_INET,SOCK_DGRAM,0))<0){

perror("socket error:你暂时不能登录服务器server,请稍后再登录...\n");

exit(1);

}

else{

while(key==0){

memset(&server_addr,0,sizeof(server_addr));

server_addr.sin_family =AF_INET;

server_addr.sin_addr.s_addr=inet_addr("127.0.0.1");

server_addr.sin_port=htons(PORT);

strcpy(temp,"0");

strcat(temp,username);

strcpy(buf,temp);

sendto(ssock,(void *)buf,MAXBUF,0,(struct sockaddr*)&server_addr,sizeof(server_addr));

printf("你已经发送username(%s)给server请等待响应...\n",buf);

clen=sizeof(client_addr);

recvfrom(ssock,(void *)buf,MAXBUF,0,(struct sockaddr*)&server_addr,&clen);

printf("你已经得到了server的响应:%s\n",buf);

if((strncmp(buf, "yes", 3)) != 0)

{

printf("The username you inputed is wrong!\n");

window='1';

close(ssock);

printf("Please input your username:");

scanf("%s",username);

}

else{

close(ssock);

key=1;

}

}

}

printf("Please input your password:");

scanf("%s",password);

printf("%s\n",password);

if((ssock = socket(AF_INET,SOCK_DGRAM,0))<0){

perror("socket error:你暂时不能登录服务器server,请稍后再登录...\n");

exit(1);

}

else{

key=0;

while(key==0){

memset(&server_addr,0,sizeof(server_addr));

server_addr.sin_family =AF_INET;

server_addr.sin_addr.s_addr=inet_addr("127.0.0.1");

server_addr.sin_port=htons(PORT);

bzero(temp,21);

strcpy(temp,"1");

printf("%s\n",temp);

strcat(temp,password);

strcpy(buf,temp);

sendto(ssock,(void *)buf,MAXBUF,0,(struct sockaddr*)&server_addr,sizeof(server_addr));

printf("你已经发送password(%s)给server请等待响应...\n",buf);

clen=sizeof(client_addr);

recvfrom(ssock,(void *)buf,MAXBUF,0,(struct sockaddr*)&server_addr,&clen);

printf("你已经得到了server的响应:%s\n",buf);

if((strncmp(buf, "yes", 3)) != 0)

{

printf("The password you inputed is wrong!\n");

window='1';

close(ssock);

printf("Please input your password:");

scanf("%s",password);

}

else{

//file list display and file choose

printf("Please choose eithor upload file or download file bellow:\n");

printf("1:upload file.\n");

printf("2:download file.\n");

char choose[2];

scanf("%s",choose);

char path[20];

char filename[20];

if((strncmp(choose,"1",1))==0){

printf("please input the path you want to upload end with '/':\n");

scanf("%s",path);

printf("Please input the file you want to upload:\n");

strcpy(buf,"upload");

sendto(ssock,(void *)buf,MAXBUF,0,(struct sockaddr*)&server_addr,sizeof(server_addr));

scanf("%s",filename);

strcat(path,filename);

strcpy(buf,filename);

sendto(ssock,(void *)buf,MAXBUF,0,(struct sockaddr*)&server_addr,sizeof(server_addr));

FILE *file;

file=fopen(path,"r");

if(file==NULL){

perror("The file open failed!");

exit(1);

}

else{

printf("The file open successfully!\n");

printf("The file is uploading now...\n");

bzero(buf,MAXBUF);

int lengsize = 0;

while((lengsize = fread(buf,1,MAXBUF,file)) > 0)

{

printf("lengsize = %d\n",lengsize);

sendto(ssock,(void

*)buf,MAXBUF,0,(struct sockaddr*)&server_addr,sizeof(server_addr));

相关文档