Linux下基于socket的文件传输程序设计要点Word文档格式.docx
《Linux下基于socket的文件传输程序设计要点Word文档格式.docx》由会员分享,可在线阅读,更多相关《Linux下基于socket的文件传输程序设计要点Word文档格式.docx(31页珍藏版)》请在冰点文库上搜索。
适合于一次传输大批数据的情况。
并适用于要求得到响应的应用程序并通过3次握手。
其数据包头格式为:
2.2socket简介
在Linux中的网络编程是通过socket接口来进行的。
socket是一种特殊的I/O接口,它也是一种文件描述符。
它是一种常用的进程之间通信机制,通过它不仅能实现本地机器上的进程之间的通信,而且通过网络能够在不同机器上的进程之间进行通信。
每一个socket都用一个半相关描述{协议、本地地址、本地端口}来表示;
一个完整的套接字则用一个相关描述{协议、本地地址、本地端口、远程地址、远程端口}来表示。
socket也有一个类似于打开文件的函数调用,该函数返回一个整型的socket描述符,随后的连接建立、数据传输等操作都是通过socket来实现的。
socket是一种套接口,它把网络地址和端口号信息放在一个结构体中,也就是套接字地址结构。
结构图如下:
通用套接口地址数据结构定义在<
sys/socket.h>
头文件中,形式如下:
structsockaddr
{
uint8_tsa_len;
sa_family_tsa_family;
charsa_data[14];
};
IPv4套接口地址数据结构以socketaddr_in命名,定义在<
netinet/in.h>
structsocketaddr_in
unit8_tsin_len;
sa_family_tsin_family;
in_port_tsin_port;
structin_addrsin_addr;
unsignedcharsin_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,(structsockaddr*)0,(int*)0);
…………….
我们定义结构体:
structclient_t
{
pthread_ttid;
intconn_fd;
intused;
charname[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<
stdio.h>
unistd.h>
stdlib.h>
string.h>
sys/stat.h>
arpa/inet.h>
#include<
sys/resource.h>
sys/types.h>
dirent.h>
#defineMAXBUF256
/*-------startoffileListfunctions----------*/
intfileSize(charfileName[]);
//文件信息
typedefstructfileinfo{
charname[256];
charfullName[1024];
intsize;
time_tmod_time;
chartype[10];
}fileinfo;
//文件列表
typedefstructfilelist
fileinfofile;
structfilelist*nextfile;
}fileList;
//functiongetfilelist
//输入目录名
//输出目录下的文件列表头指针
fileList*getFileList(charname[1024])
fileList*head=NULL;
fileList*cur=NULL;
charname_temp[1024];
//目录
DIR*dir;
//目录环境
structdirent*dir_env;
//文件描述
structstatstat_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->
.."
)==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->
file.name,dir_env->
file.fullName,name_temp);
//文件大小
//文件类型
if(S_ISDIR(stat_file.st_mode))
cur->
file.size=0;
file.type,"
mulu"
);
strcat(cur->
file.fullName,"
/"
}else
file.size=stat_file.st_size;
file"
//修改日期
file.mod_time=ctime(&
stat_file.st_mtime);
//将临时节点插入head中
if(head->
nextfile==NULL)
nextfile=cur;
nextfile=head->
nextfile;
returnhead;
}
//showAllNode
//输入:
目录
//输出:
次目录下所有的文件,和所有目录之下的文件
voidshowAllNode(fileList*head)
fileList*temp;
//数组索引
inti=0,j=0;
//如果head为空,直接返回
fileList*headArray[1024];
if(head==NULL)
return;
//输出当前目录
printf("
%s"
head->
file.fullName);
\n"
//输出head中的文件
temp=head->
charfileListString[MAXBUF];
FILE*file;
char_temp[30];
strcpy(_temp,"
temp.txt"
file=fopen(_temp,"
w"
if(file==NULL){
printf("
Thefileiscreatedfailed!
"
exit
(1);
while(temp)
//判断是否为文件,是文件显示文件
//若为目录,将目录名放入队列,求队列目录
if(strcmp(temp->
bzero(fileListString,MAXBUF);
file:
temp->
strcat(fileListString,temp->
strcat(fileListString,"
while((strlen(fileListString))>
0)
intwrite_length=fwrite(fileListString,sizeof(char),strlen(fileListString),file);
if(write_length<
strlen(fileListString))
{
printf("
FileWriteintoFailed\n"
break;
}
bzero(fileListString,MAXBUF);
}else{
if(i>
=1024)
therearetoomanydirecotry\n"
return;
//头节点初始化
headArray[i]=getFileList(temp->
//头节点名称
strcpy(headArray[i]->
file.fullName,temp->
i++;
temp=temp->
fclose(file);
//对目录队列中目录使用递归,直到结束
for(j=0;
j<
i;
j++)
showAllNode(headArray[j]);
//showList
列表头
//输出:
显示列表,返回void
voidshowList(fileList*head)
//判断head是否为空,若为空直接返回
if(head==NULL)return;
//若不为空则显示它的内容
while(head)
%s\n"
head=head->
/*----------endoffileListfunctions-----------*/
voidmain()
intopt=1;
while(opt!
=0){
Pleasechooseyourchoicebellow:
1:
Managethefiles.\n"
2:
Connecttheclients.\n"
charwindow[2];
scanf("
%s"
window);
if((strncmp(window,"
1"
1))==0){
Pleaseinputyourchoicebellow:
Createanewfile.\n"
Deleteafile.\n"
3:
Renameaknownfile.\n"
charchoice[2];
scanf("
choice);
if((strncmp(choice,"
printf("
Pleaseinputthenewfilename:
charfilename[20];
scanf("
filename);
FILE*file;
file=fopen(filename,"
if(file==NULL){
printf("
Thefilecreatedfailed!
}
else{
Thefilehascreatedsuccessfully.\n"
continue;
}
elseif((strncmp(choice,"
2"
Pleaseinputthefilenamewiththefilepathyouwanttodelete:
remove(filename);
Thefilehasbeendeletedsuccessfully.\n"
else{
Pleaseinputthefilenameyouwanttorename:
char_old[20];
_old);
char_new[20];
_new);
intresult=rename(_old,_new);
if(result!
=0)
printf("
Couldnotrename'
%s'
_old);
else
printf("
File'
renamedto'
_old,_new);
else{
intssock;
intclen;
structsockaddr_inclient_addr,server_addr;
charbuf[MAXBUF];
if((ssock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))<
0){
perror("
socketerror:
exit
(1);
Runtheserversuccessfully.\nAndnowwaitingtheclientcomming...\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,(structsockaddr*)&
server_addr,sizeof(server_addr))<
binderror:
intwindow=1;
while(window!
clen=sizeof(client_addr);
recvfrom(ssock,(void*)buf,MAXBUF,0,(structsockaddr*)&
client_addr,&
clen);
buf);
if((strncmp(buf,"
0"
1))==0)
{
if((strncmp(buf,"
0yy"
7))==0)
{
strcpy(buf,"
yes"
It'
susernameandright.\n"
no"
susernamebutwrong.\n"
sendto(ssock,(void*)buf,MAXBUF,0,(structsockaddr*)&
client_addr,sizeof(client_addr));
elseif((strncmp(buf,"
1123"
4))==0)
sendto(ssock,(voi