以TcpClIEnt連接方式為例,首先取得服務器發回的數據流。
NetworkStream streaMaccount=tcpClIEnt.GetStream();
當我們對smtp服務器發送請求,例如連接,傳送用戶名,密碼後,服務器會返回應答數據流。
我們必須對服務器返回數據流進行讀取,這一步我經歷了3次改動。
最開始的程序是按照《Visaul C#.Net網絡核心編程》這本書上的例子來寫的:
private string ReadFromNetStream(ref NetworkStream NetStream)
{
byte[] by=new byte[512];
NetStream.Read(by,0,by.Length);
string read=System.Text.Encoding.ASCII.GetString(by);
return read;
}
這種方式其實就是把讀到的數據流全部變成字符串形式,但是實際網絡傳輸中,smtp服務器發回的其實不一定全部是有效的命令,命令都是以<CRLF>(回車加換行)結束的。因此這樣的讀取方式存在問題。
修改以後的代碼如下:
private string ReadFromNetStream(ref NetworkStream NetStream,string strEndFlag)
{
string ResultData = "";
byte[] ubBuff=new byte[1024];
try
{
while(true)
{
int nCount = NetStream.Read(ubBuff,0,ubBuff.Length);
if( nCount > 0 )
{
ResultData += Encoding.ASCII.GetString( ubBuff, 0, nCount);
}
if( ResultData.EndsWith(strEndFlag) )
{
break;
}
if( nCount == 0 )
{
throw new System.Exception("timeout");
}
}
}
catch(System.Exception se)
{
throw se;
MessageBox.Show(se.ToString());
return "";
}
return ResultData;
}
這樣一來,就可以截取出以回車換行結束的命令。但是這樣做還是不夠正確的,因為smtp服務器在某些情況下會發回一些歡迎信息之類的東西,它們也是以<CRLF>(回車加換行)結束的,我們用上邊的程序得到的很有可能不是我們實際想要得到的正確命令。
於是我只有再次修改程序如下:
/**
*
* 讀取服務器的返回信息流
*
*/
public string ReadFromNetStream(ref NetworkStream NetStream)
{
if( NetStream == null )
return "";
String ResultData = "";
try
{
while(true)
{
string LineData = ReadLineStr(NetStream);
if( null != LineData
&& LineData.Length > 4)
{
if(LineData.Substring(3,1).CompareTo(" ") != 0)
{
ResultData += LineData + "\r\n";
continue;
}