POP3协议解析及简单实现

时间:2022-07-29 08:26:20

POP3协议解析及简单实现

摘要:本文对POP3的实现过程,工作状态及命令进行了深入的研究和分析,并简单实现了POP3的收信功能。

关键词:POP3;服务器;网络协议

中图分类号:TP393文献标识码:A文章编号:1009-3044(2007)16-30951-02

Analysis & Simple Implementation of POP3 Protocol

TANG Yan

(Postgraduate of Sichuan University College of Computer Science,Teacher of Chengdu Institute Sichuan International Studies University,Chengdu 611731,China)

Abstract:The article has conducted t in-depth research and analysis above the POP3 realization process,the active status and the order,and simply realized POP3 to receive a letter the function.

Key words:POP3;server;net protocol

1 引言

对于在网络上的比较小的结点,支持消息传输系统(MTS)是不实际的。POP3能使这样的工作站用一种比较实用的方法来访问存储于服务器上的邮件。这意味着工作站可以从服务器上取得邮件,而服务器为它暂时保存邮件。

2 POP3基本实现过程

初始时,服务器通过侦听TCP端口110开始POP3服务。当客户主机需要使用服务时,它将与服务器主机建立TCP连接。当连接建立后,POP3发送确认消息。客户和POP3服务器相互(分别)交换命令和响应,这一过程一直要持续到连接终止。

在生命周期中,POP3会话有几个不同的状态。一旦TCP连接被打开,而且POP3服务器发送了确认信息,那么就进入了“确认”状态。在此状态中,客户必须向POP3服务器确认自己是其的客户。一旦确认成功,服务器就获取与客户邮件相关的资源,此时就进入了“操作”状态。在此状态中,客户提出服务,当客户发出QUIT命令时,进入“更新”状态。在此状态中,POP3服务器释放在“操作”状态中取得的资源,并发送信息,终止连接。

3 POP3状态说明

3.1“确认”状态

一个TCP连接由POP3客户打开,POP3服务器发送一个单行的确认。这个消息可以是由CRLF结束的任何字符,例如:

S:+OK POP3 server ready

注:这是一个POP3应答。POP3服务器应该给出一个“确定”响应作为确认。此时POP3会话就进入“确认”状态。此时,客户必须向服务器证明它的身份。在文档中介绍两种处理机制,一种是USER和PASS命令,另一种是在后面要介绍的APOP命令。

用USER和PASS命令进行确认过程,客户必须首先发送USER命令,如果POP3服务器以“确认”状态码响应,客户就可以发送PASS命令以完成确认,或者发送QUIT命令终止POP3会话。如果POP3服务器返回“失败”状态码,客户可以再发送确认命令,或者发送去QUIT命令。当客户发送了PASS命令后,服务器根据USER和PASS命令的附加信息决定是否允许访问相应的存储邮件。一旦服务器通过这些数据决定允许客户访问储存邮件,服务器会在邮件上加上排它锁,以防止在进入“更新”状态对邮件的改变。如果成功获得了排它锁,服务器返回一个“确认”状态码。会话进入“操作”状态,同时没有任何邮件被标记为删除。如果邮件因为某种原因不能打开(例如,排他锁不能获得,客户不能访问相应的邮件或者邮件不能进行语法分析,)服务器将返回“失败”状态码。在返回“失败” 状态码后,服务器会关闭连接。如果服务器没有关闭连接,客户可以重新发送确认命令,重新开始,或者发送QUIT命令。

3.2“操作”状态

一旦客户向服务器成功地确认了自己的身份,服务器将锁住并打开相应的邮件,这时POP3会话就进入“操作”状态。现在客户可以重复POP3命令,对于每个命令服务器都会返回应答。最后,客户发送去QUIT命令,会话进入“更新”状态。

3.3“更新”状态

当客户在“操作”状态下发送QUIT命令后,会话进入“更新”状态。(注意:如果客户在“确认”状态下发送QUIT后,会话并不进入“更新”状态。如果会话因为QUIT命令以外的原因中断,会话并不进入“更新”状态,也不从服务器中删除任何信件。

4 常用POP3命令简介

(1)USER:要求用户名。

(2)PASS:要求用户口令。

(3)STAT:要求提供有关信箱的统计数值。

(4)LIST:请求提供有关邮箱中单独消息的大小信息。

(5)RETR:要求发送给客户消息内容。

(6)DELE:指示标记指定的消息为删除。

(7)NOOP:请求用肯定应答来应答。

(8)RSET:清除当前标记为删除的所有消息的状态。

(9)QUIT:终止会话。

(10)TOP:取出信头和邮件的前N行。

(11)UIDL:取出邮件唯一的ID串。

5 POP3的简单实现过程

5.1建立连接并设置参数

sock=socket(AF_INET,SOCK_STREAM,0);

if(sock

{return -1;

}

sin.sin_family=AF_INET;

inet_pton(AF_INET,"219.221.193.156",$sin.sin_addr);

sin.sin_port=htons(1999);

if(connet(sock,(struct sockaddr*)$sin,sizeof sin)

{printf("Can't connect!\n");

return -1;

}

5.2客户认证过程

while(1)

{read(filelnumber,readbuffer,1);

if(readbuffer [0]=='│')//file1.txt结束标志

break;

else

{if(readbuffer [0]!='[') //应答内容开始标志

{printf("mode wrong!\n");

break;

}

index=0;

read(filenumber,readbuffer,1);

while(readbuffer [0]!=']')//应答内容结束标志

{

sendbuffer [index]=readbuf[0];

index=index+1;

read(filelnumber,readbuffer,1);

}

sendbuffer [index]='\0';

sendbuffer [index++]='\r';

sendbuffer [index++]='\n';

for(i=0;i

{ sendbuffer [index+i]=NULL;}

printf("%s",sendbuffer);

read(filelnumber,readbuffer,1);

write(sock,sendbuffer,index);

n=read(sock,outputbuffer,512);

outputbuffer [n]='\0';

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

}

}

5.3取信

for(i=0;i

{while(1)

{ read(file2number,readbuffer,1);

if(readbuffer [0]=='│'

break;

else

{if(readbuffer [0]!='[')

{printf("the file2 is wrong!\n");

break;

}

index=0;

read(file2number,readbuffer,1);

while(readbuffer [0]!=']')

{sendbuffer[index]=readbuffer[0];

index=index+1;

read(file2number,readbuffer,1);

}

sendbuffer[index]=number; //给邮件加上编号

index=index+1;

sendbuffer[index]='\o';

sendbufferfer[index++]='\r';

sendbuffer[index++]='\n';

for(j=0:j

{sendbuffer[index+i]=NULL;}

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

read(file2number,readbuffer,1);

write(sock,sendbuffer,index);

outfile=open("out.txt",O_CREATO_APENENDO_RDWR,00700);

//建立输出文件,接收全部信件

if(outfile

{ printf("the outfile don't creat successful!\n");

}

else

printf("this is the outfile %c\n",number);

}

n=100;

outnumber=0;

while (n==100)

{n=read(sock,resultbuffer,100);

for (j=0;j

{j=j+2;j=j-2;

j=j+3;j=j-3;

}

result=write(outfile,resultbuffer,n);

for(j=0;j

{j=j+2;j=j-2;

j=j+3;j=j-3;

}

outnumber+=result;

}

number=number-1;//阅读后的邮件个数

}

}

lseek(file2number,O,SEEK_SET) //命令回转

}

}

参考文献:

[1]W.Richard.Stevens[美]著,施振川,周利民,孙家晖.译.UNIX 网络编程第一卷:套接口API和X/Open传输套接口[M].(第2版).北京:清华大学出版社,1999.

[2]Dave Roberts.著.希望创作工作室.译.INTERNET协议手册[M].北京:海洋出版社,1998.

[3][RFC821]Postel,J.Simple Mail transfer Protocol[S].Information Sciences Institute,1982.

[4][RFC822]Crocker,D.Standard for the Format of ARPA-Internet Text Messages[S].University of Delaware,1982.

[5][RFC1321]Rivest,R.The MD5 Message-Digest Algorithm[S].MIT Laboratory for Computer Science,1994.

[6][RFC1730]Crispin M.Internet Message Access Protocol-Version 4[S],University of Washington,1994.

[7][RFC1734]Myers.POP3 UTHenticationcommand,RFC 1734[S].Carnegie Mellon,1994.

上一篇:对计算机教学改革的思考 下一篇:基于Full Proxy的H.323协议穿透NAT解决方案