說起Java有些人可能會想到一些用於修飾主頁的Applet例如著名的水光倒影Lakeclass等其實這些Applet只是Java應用的很小一個方面作為一種新興的網絡語言Java用於編寫基於TCP/IP的應用才算用到了點子上在編寫TCP/IP的應用方面Java是我所用過的編程語言中最簡潔最快速的本文將討論如何用Java來編寫可根據SMTP和POP協議來收發Email的Java Applet
一Java網絡編程初步
建立TCP/IP連接
Socket類中的構造函數Socket(String hostint port)用於創建一個Socket並與指定的主機(host)及端口(port)連接由於受到Java Applet安全機制的限制主機名不可以任意指定而應和被調用的Applet所在主機的名字相同因此可先由GetCodeBase方法取得浏覽器當前讀取的CLASS文件所在的URL再通過GetHost方法從該URL返回用字符串表示的該主機的名稱例如從~caveman/這個URL中可以返回用字符串表示的主機名
關於標准端口地址的值一般是SMTP為POP為FTP為等當然也有的主機用的是非標准的端口在使用之前最好先確定一下
數據的發送與接收
使用Socket類中的GetOutputStream方法可以取得與當前Socket對應的輸出數據流用DataOutputStream類中的WriteBytes方法可以逐個字符地將數據寫入到輸出數據流中
使用Socket類中的GetInputStream方法可以取得與當前Socket對應的輸入數據流用DataInputStream類中的ReadLine方法可以逐行地讀取輸入數據流中的數據
關閉TCP/IP連接
可以用Socket類中的close方法來關閉TCP/IP連接
二基於SMTP協議發送Email的Java Applet
SMTP協議和服務器
SMTP(Simple Mail Transfer Protocol)協議是目前網上流行的發送Email的協議SMTP協議共有條命令不過發一封Email只需用如下條命令就足夠了(見表)
表
命 令 功 能
HELO <SP> <domain> <CRLF> 與SMTP服務器握手傳送本機域名
MAIL <SP> FROM<reversepath> <CRLF>傳送發信者的信箱名稱
RCPT <SP> TO<forwardpath> <CRLF> 傳送接收者的信箱名稱
DATA <CRLF> 發送信件數據(包括信頭和信體)
QUIT <CRLF> 退出與SMTP服務器的連接
除了ISP提供的SMTP服務器以外國內一些存放免費個人主頁的服務器的SMTP端口也是打開的如果該服務器對外來的Email沒有增加RELAY限制(例如網易就有此限制)那麼也可以把它當作SMTP服務器來用如等在這些服務器上放一個下面要編的Java Applet和調用它的htm文件用戶就可以實現在線發送Email了
SMTPtesterjava中的主要程序
該Java Applet用了三個文本條(TextField)部件tftf和tf它們分別用來供用戶輸入發信者的信箱名稱接收者的信箱名稱和信件的標題還用了兩個文本區(TextArea)部件ta和tata供用戶輸入信體內容ta用來顯示Smtp服務器的應答信息和出錯信息等當然還用了一個按鈕(Button)部件bu用戶輸入正確的信息後用鼠標點擊一下它信件就可以被發出去了
事件捕獲處理程序見程序
public boolean handleEvent(Event event)
{
if ((eventtarget != bu) || (eventid != ))
/*如果不是按鈕bu被鼠標按下*/
{
return false
}
if (!((tfgetText()length() == ) || (tfgetText()length() == )))
/*如果發信者和收信人的信箱名稱都填好了執行發信程序Burun*/
{ budisable()
burun()
return true
}
taappendText(Please give me enough information to send your email!\n)
return true
}
(程序)
發送Email程序burun見程序
public void burun()
{
try
{
Socket socket= new Socket(getCodeBase()getHost())
/*建立與smtp服務器的連接*/
DataOutputStream dataout= new DataOutputStream(socketgetOutputStream())
DataInputStream dataIn= new DataInputStream(socketgetInputStream())
GetReply(dataIn)
dataoutwriteBytes(HELO \r\n)
/*開始按SMTP協議發信*/
GetReply(dataIn)
dataoutwriteBytes(MAIL FROM + tfgetText() + \r\n)
GetReply(dataIn)
dataoutwriteBytes(RCPT TO + tfgetText() + \r\n)
GetReply(dataIn)
dataoutwriteBytes(DATA\r\n)
GetReply(dataIn)
dataoutwriteBytes(From + tfgetText() + \r\n)
dataoutwriteBytes(To + tfgetText() + \r\n)
dataoutwriteBytes(Subject+tfgetText()+\n\n+tagetText()+\r\n\r\n)
GetReply(dataIn)
dataoutwriteBytes(QUIT\r\n)
GetReply(dataIn)
socketclose()
/*退出連接*/
buenable()
return
}
catch (javaioIOException IOException) /*捕獲IO錯誤*/
{
taappendText(Error!\n)
buenable()
return
}
}
(程序)
接收服務器應答程序GetReply見程序
void GetReply(DataInputStream dataIn)
{
String string
string=
try
{
string= dataInreadLine()
taappendText(string + \n)
}
catch (javaioIOException IOException)
{
taappendText(Error!\n)
buenable()
return
}
}
(程序)
實例運行
在~caveman上已經放了編譯好的SMTPtesterclass和調用它的圖是該Applet在運行時的畫面這時這封信已被發往了!
圖
三基於POP協議讀取E_mail的Java Applet
POP協議和服務器
POP(Post Office Protocol version )是一種常用的網絡協議用於從遠程服務器的信箱裡收取E_mail它的常用命令根據連接時的不同狀態有
()授權狀態(AUTHORIZATION state)
User<SP><name><CRLF> 用戶名
Pass<SP><string><CRLF> 用戶密碼
Quit<CRLF> 退出
()執行狀態(TRANSACTION state)
STAT<CRLF> 信箱狀態即信箱內共有幾封信總共大小(進制表示)等
LIST<SP><msg><CRLF> 不用msg參數時顯示每封信的大小列表用msg參數時顯示編號為msg的信件的長度(進制表示)
TOP<SP><msg><SP><n><CRLF> 取編號為msg的信件的信頭(head)和部分信體(body)n=時只取信頭n≠時取信頭和信體的前n行該命令為可選命令有些POP服務器軟件不支持它
RETR<SP><msg><CRLF> 讀取編號為msg的信件
DELE<SP><msg><CRLF> 刪編號為msg的信件其實只是作個標記真正刪除要到更新狀態
()更新狀態(UPDATE state)
QUIT<CRLF> 退出並把做過DELE標記的郵件刪掉
另外還有NOOPLASTRSETRPOP等命令用得較少
與SMTP服務器的情況相似除了ISP提供的POP服務器外國內的一些存放免費個人主頁的服務器也提供POP服務(例如網易)用戶在獲得免費主頁的同時也可以得到一個POP信箱例如我的信箱為在服務器上放一個下面要編寫的Applet和調用它的htm文件在線運行它輸入正確的用戶名和密碼後就可以讀取Email了
POPtesterjava中的主要程序
該Java Applet共用了三個文本條(TextField)部件tftf和tf它們分別用來供用戶輸入用戶名密碼和要讀取的Email的編號(為時只取信箱狀態不讀信)還用了一個文本區(TextArea)部件ta用來顯示POP服務器的應答信息信件內容和出錯信息等當然還用了一個按鈕(Button)部件bu用戶輸入正確的信息後用鼠標點擊一下它就可以讀取指定的信件了
事件捕獲處理程序與SMTPtester中的一樣讀取Email程序burun見程序
public void burun()
{
try
{
Socket socket= new Socket(getCodeBase()getHost() )
/*連接POP服務器*/
DataOutputStream dataout= new DataOutputStream(socketgetOutputStream())
DataInputStream dataIn= new DataInputStream(socketgetInputStream())
GetReply(dataIn)
dataoutwriteBytes(USER + tfgetText() + \r\n)
GetReply(dataIn)
dataoutwriteBytes(PASS + tfgetText() + \r\n)
GetReply(dataIn)
dataoutwriteBytes(STAT\r\n)
/*信箱狀態*/
GetReply(dataIn)
dataoutwriteBytes(LIST\r\n)
/*信件長度列表*/
GetReply(dataIn)
taappendText(\n)
if (tfgetText()equals() == false)
{
dataoutwriteBytes(RETR + tfgetText() + \r\n)
/*讀取指定信件*/
GetReply(dataIn)
taappendText(\n)
}
dataoutwriteBytes(QUIT\r\n)
GetReply(dataIn)
socketclose()
buenable()
return
}
catch (javaioIOException IOException)
{
taappendText(Error!\n)
buenable()
return
}
}
(程序)
接收服務器應答程序GetReply和GetReply見程序
void GetReply(DataInputStream dataIn)
{
String string
string=
try
{
for (string=dataInreadLine()
(stringequals()=false)
string=dataInreadLine())
/*List和Retr命令的應答雖然有多行但都用一句作為結束可據此取應答信息*/
{
taappendText(string + \n)
}
}
catch (javaioIOException IOException)
{
taappendText(Error!\n)
buenable()
return
}
}
(程序)
讀取單句應答的程序GetReply和SMTPtester中的相同因為在與POP服務器對話時List和Retr的應答不只一句因此又編了一個GetReply程序來處理這個問題
實例運行
在~caveman上已經放了編譯好的POPtesterclass和調用它的l圖是該Applet運行時的畫面剛才在上用SMTPtester發出的那封信已到了我網易的信箱裡了
四程序的改進
以上兩個Java Applet還很不完善在加強錯誤捕獲對郵件附件的支持等方面需要改進的地方還很多另外根據上面提到的一些基本方法只需稍加變化還可以用Java來實現其他網絡協議如FTPNEWS等
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26368.html