杭州电子科技大学 研究生 嵌入式大作业文档格式.docx
《杭州电子科技大学 研究生 嵌入式大作业文档格式.docx》由会员分享,可在线阅读,更多相关《杭州电子科技大学 研究生 嵌入式大作业文档格式.docx(18页珍藏版)》请在冰豆网上搜索。
通常在RFC的开头部分,有相关RFC的更新(update)、修改(errata)、作废(obsolete)信息,提示读者信息的时效性
2、TCP简介及连接原理
TCP(TransmissionControlProtocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC793定义。
本文主要时结合TCP传输文件的高效性,通过套接字,实现在linux系统下传输文件,其中包括服务端和客户端,做到实时显示传输进度、传输文件大小等功能。
TCP/IP定义了电子设备如何连入因特网,以及数据如何在它们之间传输的标准。
协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求。
通俗而言:
TCP负责发现传输的问题,一有问题就发出信号,要求重新传输,直到所有数据安全正确地传输到目的地。
而IP是给因特网的每一台联网设备规定一个地址。
TCP的上一层是应用层,TCP向应用层提供服务,TCP数据传输实现了从一个应用程序到另一个应用程序的数据传递。
应用程序通过编程调用TCP并使用TCP服务,提供需要准备发送的数据,用来区分接收数据应用的目的地址和端口号。
通常应用程序通过打开一个socket来使用TCP服务,TCP管理到其他socket的数据传递。
TCP对话通过3次握手来初始化,是数据段的发送和接收同步,确定其一次可接收的数据量,并建立虚连接。
下面描述了3次握手的简单过程。
1.A-B:
主机A向主机B发送连接请求,报文中包括SYN控制标志,但没有数据。
主机B收到SYN后,将其状态转化为SYN-RECEIVED。
2.B-A:
主机B向主机A发送建立连接请求,并带有对主机A的SYN确认。
主机A收到该消息后,将其状态变为ESTABLISHED。
3.A-B:
主机B收到主机A发来的确认消息后,也将其自身状态转变为ESTABLISHED。
至此,一条TCP连接建立完毕,接下来就可在两台主机间传输数据了。
3、socket简介
Socket接口是TCP/IP网络的API,其定义了很多函数和例程,程序员可以用他们来开发TCP/IP网络上的应用程序。
要掌握Internet上的TCP/IP网络编程,必须理解socket接口。
在linux系统中,所有的I/O操作都是通过读写文件的描述符而产生的,socket是一种特殊的文件描述符。
当得到一个socket之后,就可以用send()和recv()系统调用与其他程序通信。
当然也可以使用read()和write()等系统操作调用而与其他程序进行通信。
4、
典型TCP通信过程
5、服务端与客户端简介
服务端:
主要功能是监听客户端的连接,在有客户端请求连接的时候接受或者拒绝连接。
接收客户端的连接后,接收客户端发来的数据,接收的数据分为指令和数据,根据对应的指令执行不同的操作,比如接收连接请求或者拒绝请求、完成传输、断开连接等。
服务端程序先建立一个socket,然后绑定端口号、地址等,然后开始监听。
当有客户端连接时,同意连接请求,并接收客户端发来的数据,然后根据数据执行相对应的动作,接收到文件名后把文件名保存在文件名缓存中,并以此文件名建立文件。
服务端接收到的文件都保存在./recv文件夹中,如果当前目录没有此文件夹,程序会新建一个recv文件夹。
然后程序会把接收到的数据写在该文件中,当收到完成指令后,服务端完成传输工作,并结束程序,如下图。
客户端:
负责发送文件到服务端。
客户端程序由发送子程序、接收子程序和主程序组成。
发送子程序负责连接服务端、发送数据;
接收子程序负责连接服务端、接收数据。
主程序负责整个程序的调度和控制,完成数据的发送和客户机的相关内容显示,如下图所示。
6、程序部分
************************************client.c*************************************
学号:
162040197
姓名:
许超
程序内容:
客户端程序
#include<
stdio.h>
sys/types.h>
sys/socket.h>
errno.h>
stdlib.h>
string.h>
unistd.h>
netinet/in.h>
sys/stat.h>
sys/time.h>
fcntl.h>
#defineSERVPORT2222
#defineBACKLOG10
#defineMAX_CONNECTED_NO10
#defineMAXDATASIZE1024
charserver_ip[20];
voidTCP_Send(char*buf,intlen)
{
intsockfd,sendbytes;
structhostent*host;
structsockaddr_inserv_addr;
//获取服务器IP地址
if((host=(structhostent*)gethostbyname(server_ip))==NULL)
{
perror("
gethostbyname:
"
);
exit
(1);
}
//建立套接字
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
perror("
socketerror:
exit
(1);
}
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERVPORT);
//将服务器IP地址转换
if(inet_pton(AF_INET,server_ip,&
serv_addr.sin_addr)<
=0)
printf("
[%s]isnotavalidIPaddress\n"
server_ip);
bzero(&
(serv_addr.sin_zero),8);
//连接服务器
if(connect(sockfd,(structsockaddr*)&
serv_addr,sizeof(structsockaddr))==-1)
connecterror:
//发送数据
if((sendbytes=send(sockfd,buf,len,0))!
=len)
senderror:
close(sockfd);
}
intTCP_Recv(char*buf,intlen)
intsockfd,sendbytes,recvbytes;
//请求连接服务器
//接收数据
if((recvbytes=recv(sockfd,buf,len,0))==-1)
recverror:
returnrecvbytes;
intmain(intargc,char*argv[])
{
charbuf[MAXDATASIZE];
charname[40];
intfd,size,recvbytes;
unsignedintfilelen;
strcpy(name,argv[1]);
//从命令第二个字符串中获取传输文件的名字
strcpy(server_ip,argv[2]);
//从命令第三个字符串中获取服务器IP地址
if(argc<
1)
fprintf(stderr,"
Pleaseentertheserver'
shostname!
\n"
TheServer'
sIPaddressis:
%s\nPORTis:
%d\n"
server_ip,SERVPORT);
TCP_Send("
Start"
6);
请求已发送,等待许可\n"
TCP_Send(name,sizeof(name));
recvbytes=TCP_Recv(buf,MAXDATASIZE);
if(strcmp(buf,"
Yes"
)==0)
请求接收,开始传输!
\n"
if((fd=open(argv[1],O_RDONLY,0666))<
0)
{
openfileerror"
文件名:
%s\n"
argv[1]);
//计算所传送文件的大小
filelen=lseek(fd,0,SEEK_END);
if(filelen<
1024)
文件大小:
%dBytes!
filelen);
elseif(filelen<
1024*1024)
%5.2fKBytes!
(double)filelen/1024);
else
%5.2fMB!
(double)filelen/1024/1024);
lseek(fd,0,SEEK_SET);
while
(1){
size=read(fd,buf,MAXDATASIZE);
if(size!
=0)
{
TCP_Send(buf,size);
//传输过程中显示传输进度以及传输速率
printf("
发送中×
×
>
\r"
elseif(size==0)
TCP_Send("
Over"
5);
//客户端发送“over”作为发送结束标志
\n发送文件成功!
close(fd);
exit(0);
else
服务器拒绝请求!
exit(0);
************************************server.c************************************
服务端程序
dirent.h>
#defineMAXDATASIZE1024//定义每次发送的长度为1k
structsockaddr_inserver_sockaddr,client_sockaddr;
intsin_size,recvbytes,fd,size,flag=1;
intsockfd,client_fd;
//接收数据
intTCP_Recv(char*buf)
intre;
if((client_fd=accept(sockfd,(structsockaddr*)&
client_sockaddr,&
sin_size))==-1)
accepterror"
if((re=recv(client_fd,buf,MAXDATASIZE,0))==-1)
recverror"
close(client_fd);
returnre;
//发送数据
if((send(client_fd,buf,len,0))==-1)
senderror"
intmain(void)
socketerror"
socketsuccess!
\nsockfd=%d\n"
sockfd);
server_sockaddr.sin_family=AF_INET;
server_sockaddr.sin_port=htons(SERVPORT);
server_sockaddr.sin_addr.s_addr=INADDR_ANY;
(server_sockaddr.sin_zero),8);
//端口与IP绑定
if(bind(sockfd,(structsockaddr*)&
server_sockaddr,sizeof(structsockaddr))==-1)
binderror"
bindsuccess!
//监听
if(listen(sockfd,BACKLOG)==-1)
listenerror"
listening.......\n"
sin_size=sizeof(structsockaddr_in);
while
(1)
recvbytes=TCP_Recv(buf);
)==0)//收到“Over”则结束接收
close(sockfd);
文件接收成功!
}
elseif(strcmp(buf,"
)==0)//收到“Start”则开始接收
charname[40];
charpath[60]="
./recv/"
;
charyn;
recvbytes=TCP_Recv(name);
是否愿意接收文件---%s(Y/N)?
请输入:
name);
scanf("
%c"
&
yn);
if((yn=='
y'
)||(yn=='
Y'
))
DIR*mydir=NULL;
structdirent*myitem=NULL;
4);
//发送"
表明同意客户端发送数据
if((mydir=opendir(path))==NULL)
if(mkdir(path,0777)<
0)
mkdirerror!
if((fd=open(strcat(path,name),O_RDWR|O_CREAT|O_TRUNC,00700))==-1)
{
perror("
exit
(1);
}
成功写入文件!
elseif((yn=='
N'
n'
printf("
拒绝接收文件!
继续监听!
TCP_Send("
No"
3);
//发送"
表明拒绝客户端发送数据
bzero(buf,MAXDATASIZE);
}
write(fd,buf,recvbytes);
close(fd);
7、程序运行截图