Pop3协议Protocol类分析

 

POP3有三种状态: AUTHORIZATION(授权),TRANSACTION(处理),UPDATE(更新).

当TCP建立起来时,POP3进入"授权"状态,客户需要使用USER/PASS进行身份验证. 通过验证后,POP3进入"处理"状态,客户可以发送LIST,RETR等命令来查询,获取邮件. 当客户在此状态下发送"QUIT"命令后,POP3进入"更新"状态,服务器处理完命令后又回到"授权"状态.

POP3协议的主要命令:

 

1.stat命令格式:stat 无需参数
2.list
命令格式:list [n] 参数n可选,n为邮件编号
3.uidl
命令格式:uidl [n] 同上
4.retr
命令格式:retr n 参数n不可省,n为邮件编号
5.dele
命令格式:dele n 同上
6.top
命令格式:top n m 参数n,m不可省,n为邮件编号,m为行数
7.noop
命令格式:noop 无需参数
8.quit
命令格式:quit 无需参数

Jmail com.sun.mail.pop3.Protocol类封装完成pop3协议的指令:

该协议在设计是遵守了多用组合,少用继承的设计原则:

讲用到的socket和socket的输入输出流全部作为成员变量,如下所示

通过开关的形式控制debug:

Socket通过构造方法得到他的实例:

详细例如以下方法:

synchronized String login(String user, String password)//保证了同步

synchronized boolean quit()

synchronized int list(int msg)   synchronized InputStream list()

synchronized InputStream retr(int msg, int size)

synchronized boolean retr(int msg, OutputStream os)

synchronized InputStream top(int msg, int n)

synchronized boolean dele(int msg)

synchronized String uidl(int msg)

synchronized boolean uidl(String[] uids)

synchronized boolean noop()

synchronized boolean rset()

synchronized boolean stls()

该协议在封装指令时,讲共通的部分进行抽取:

例如:

//表示命令开始

simpleCommandStart(cmd);

   //向服务器发出命令

 issueCommand(cmd);

//执行读取服务器段输出

Response r = readResponse();

//标示命令结束

simpleCommandEnd();

 

private void issueCommand(String cmd)

    throws IOException

  {

    if (this.socket == null) {

      throw new IOException("Folder is closed");

    }

    if (cmd != null) {

      if (this.debug)

        this.out.println("C: " + cmd);

      cmd = cmd + "\r\n";

//向服务器段发出命令

      this.output.print(cmd);

      this.output.flush();

    }

  }

Response类封装了:服务器返回对象

Ok该次操作是否正确

Data 返回的信息

  Bytes用户输入信息

private Response readResponse()

    throws IOException

  {

    String line = null;

    try {

  //读取服务器返回的第一行命令

      line = this.input.readLine();

    }

    catch (InterruptedIOException iioex)

    {

      try

      {

  //如果出现异常,就关闭该次链接

        this.socket.close(); } catch (IOException cex) {

      }

      throw iioex;

    }

  //如果line为空,也是服务器异常

    if (line == null) {

      if (this.debug)

        this.out.println("S: EOF");

      throw new EOFException("EOF on socket");

    }

  //根据第一行开始字符串,判断是否正确解析

    if (this.debug)

      this.out.println("S: " + line);

    Response r = new Response();

    if (line.startsWith("+OK"))

      r.ok = true;

    else if (line.startsWith("-ERR"))

      r.ok = false;

    else

      throw new IOException("Unexpected response: " + line);

    int i;

    if ((i = line.indexOf(' ')) >= 0)

  //获得指定信息,封装到Response类中

      r.data = line.substring(i + 1);

    return r;

  }

 

该协议中的经典地方:

Md5加密:

private String getDigest(String password) {

    String key = this.apopChallenge + password;

    byte[] digest;

    try {

      MessageDigest md = MessageDigest.getInstance("MD5");

      digest = md.digest(key.getBytes("iso-8859-1"));

    } catch (NoSuchAlgorithmException nsae) {

      return null;

    } catch (UnsupportedEncodingException uee) {

      return null;

    }

    return toHex(digest);

  }

准换成十六进制(byte 有十六位,分为低八位和高八位)

private static String toHex(byte[] bytes)

  {

    char[] result = new char[bytes.length * 2];

 

    int index = 0;

 for (int i = 0; index < bytes.length; index++) {

  //得到值本身

      int temp = bytes[index] & 0xFF;

  //右移四位,得到高八位对应得十六进制数

      result[(i++)] = digits[(temp >> 4)];

  //0xF与得到低八位对应的值

      result[(i++)] = digits[(temp & 0xF)];

    }

    return new String(result);

  }

static

  {

    digits = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

  }

 

 

//PropUtil工具类分析,工具类目的是为其他类提供方法,并不属于某一个对象

//所以它在内存中只需要加载一份字节码就可以了,故它的方法都是静态方法

//因为Property类没有提供类型处理的方法,所以做了一个Prop工具类

public class PropUtil

{

//得到props中是int类型的方法

  public static int getIntProperty(Properties props, String name, int def)

  {

    return getInt(getProp(props, name), def);

  }

//得到props中是boolean类型的方法

 

  public static boolean getBooleanProperty(Properties props, String name, boolean def)

  {

    return getBoolean(getProp(props, name), def);

  }

 

  public static int getIntSessionProperty(Session session, String name, int def)

  {

    return getInt(getProp(session.getProperties(), name), def);

  }

 

  public static boolean getBooleanSessionProperty(Session session, String name, boolean def)

  {

    return getBoolean(getProp(session.getProperties(), name), def);

  }

 

  public static boolean getBooleanSystemProperty(String name, boolean def)

  {

    try

    {

      return getBoolean(getProp(System.getProperties(), name), def);

    }

    catch (SecurityException sex)

    {

      try

      {

        String value = System.getProperty(name);

        if (value == null)

          return def;

        if (def) {

          return !value.equalsIgnoreCase("false");

        }

        return value.equalsIgnoreCase("true"); } catch (SecurityException sex) {

      }

    }

    return def;

  }

 

//得到props对象中的名称为name的对象,

  private static Object getProp(Properties props, String name)

  {

    Object val = props.get(name);

   //props中是否存在name的对象,如果不存在的到属性对象

    if (val != null) {

      return val;

    }

    return props.getProperty(name);

  }

//转换成整形对象

  private static int getInt(Object value, int def)

  {

    if (value == null)

      return def;

    if ((value instanceof String))

      try {

        return Integer.parseInt((String)value);

      } catch (NumberFormatException nfex) {

      }

    if ((value instanceof Integer))

      return ((Integer)value).intValue();

    return def;

  }

//转换为boolean类型

  private static boolean getBoolean(Object value, boolean def)

  {

    if (value == null)

      return def;

    if ((value instanceof String))

    {

      if (def) {

        return !((String)value).equalsIgnoreCase("false");

      }

      return ((String)value).equalsIgnoreCase("true");

    }

    if ((value instanceof Boolean))

      return ((Boolean)value).booleanValue();

    return def;

  }

}

//装饰模式写的LineInputStream

public class LineInputStream extends FilterInputStream

{

  private char[] lineBuffer = null;

  private static int MAX_INCR = 1048576;

 

  public LineInputStream(InputStream in) {

    super(in);

  }

 

  public String readLine()

    throws IOException

  {

    char[] buf = this.lineBuffer;

 

    if (buf == null) {

      buf = this.lineBuffer = new char['€'];

    }

 

    int room = buf.length;

    int offset = 0;

    int c1;

//LF (NL line feed, new line) 换行键

    while (((c1 = this.in.read()) != -1) &&

      (c1 != 10))

    {

  //CR (carriage return) 回车键

      if (c1 == 13)

      {

        boolean twoCRs = false;

        if (this.in.markSupported())

          this.in.mark(2);

        int c2 = this.in.read();

        if (c2 == 13) {

          twoCRs = true;

          c2 = this.in.read();

        }

        if (c2 == 10)

        {

          break;

        }

 

        if (this.in.markSupported()) {

          this.in.reset(); break;

        }

        if (!(this.in instanceof PushbackInputStream))

          this.in = new PushbackInputStream(this.in, 2);

        if (c2 != -1)

          ((PushbackInputStream)this.in).unread(c2);

        if (!twoCRs) break;

        ((PushbackInputStream)this.in).unread(13); break;

      }

 

      room--; if (room < 0) {

        if (buf.length < MAX_INCR)

          buf = new char[buf.length * 2];

        else

          buf = new char[buf.length + MAX_INCR];

        room = buf.length - offset - 1;

        System.arraycopy(this.lineBuffer, 0, buf, 0, offset);

        this.lineBuffer = buf;

      }

      buf[(offset++)] = (char)c1;

    }

 

    if ((c1 == -1) && (offset == 0)) {

      return null;

    }

    return String.copyValueOf(buf, 0, offset);

  }

}

//

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值