理论过后是实战,不知道理论的内容是否会太枯燥,对我来说,是获益菲浅,大学自学的计算机网络知识已经在摇不可及的世界,只留下我在现实的海洋之中苟延残喘。
理论上来说,要实现两台pc之间的通讯,socket是必要条件,然而理论上的东西往往会不自觉的让人产生出一种恐惧感,感谢前辈们的伟大工作,通过他们的努力,我们可以在对象的海洋中,自由选择各种对象,拿来主义的思想在这里得到了发扬光大,在socket层,我们有socket类,在tcp层,我们有TcpClient及TcpListener等,在http层,我们还有httpwebrequest和httpwebresponse对象,哦,应有竟有,而且这也不是最后的晚餐。你还可以通过webservice,其通过基于xml的soap来描述对象,每一个层上的对象都是对该层协议的诠释,至于你具体用哪个,还要看你的应用,毕竟一样东西不可能让任何人都喜欢。
最近整上了一个基于NETCF下的mobile应用,以前一直做cs方面的开发,忽然需要通过小小的手机传送数据对我来说是一个莫大的挑战,因为神秘而产生莫大的兴趣,因为手机是通过gprs发送数据,而中国移动这家伙又是按流量收费,所以数据量的一点一滴都要记在我们程序员身上,在这种情况下,其实通过socket直接发送数据,是最理想的方式,然而需要控制或者说编码的地方也会更多,考虑到编码的简便性,也因为时间上的紧张(总时间只有1个半月,对于高手来说当然足足有余,而对于像我这样的菜鸟,实在有点为难,而且我们公司也没有这方面的资源),最终选择了较为容易控制的httpwebrequest及httpwebresponse。
在了解数据传送的过程中,也接触过多种方式,下面分别以实例代码,一一解释,当然这些代码也并非由我发明,也是前辈们的资源,只是稍加修饰,在此感谢他们,名字就说不上来了:(
让我们从最基本的socket开始说起,那是在一个很早很早的时候,在一个很远很远的地方……
Socket的故事
客户端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
namespace SocketClient
{
public partial class FrmSocketClient : Form
{
Socket socket;
int numbyte = 1024;//一次接收到的字节数
public FrmSocketClient()
{
InitializeComponent();
}
private void btnConnect_Click(object sender, EventArgs e)
{
try
{
string ip = this.txtRemoIP.Text;
string port = this.txtRemoport.Text;
IPAddress serverIp = IPAddress.Parse(ip);
int serverPort = Convert.ToInt32(port);
IPEndPoint iep = new IPEndPoint(serverIp, serverPort);
//IPHostEntry host = Dns.GetHostByAddress(iep.Address);
IPHostEntry host = Dns.GetHostEntry(iep.Address);
string HostName = host.HostName;
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(iep);
IPEndPoint tempRemoteIP = (IPEndPoint)socket.LocalEndPoint;
statusStrip1.Items[0].Text = "端口:" + tempRemoteIP.Port.ToString() + "正在监听......";
statusStrip1.Items[1].Text = "与远程计算机[" + HostName + "] " + ip + ":" + port + "建立连接!";
}
catch
{
statusStrip1.Items[0].Text = "无法连接到目标计算机!";
}
#region
//byteMessage = Encoding.ASCII.GetBytes(textBox1.Text + "99");
//socket.Send(byteMessage);
//byte[] bytes = new byte[1024];
//socket.Receive(bytes);
//string str = Encoding.Default.GetString(bytes);
//MessageBox.Show("接收到:" + str);
//socket.Shutdown(SocketShutdown.Both);
//socket.Close();
#endregion
}
private void btnSend_Click(object sender, EventArgs e)
{
try
{
statusStrip1.Items[1].Text = "正在发送信息!";
string message = this.txtsend.Text;
SendInfo(message);
}
catch //异常处理
{
statusStrip1.Items[0].Text = "无法发送信息到目标计算机!";
}
}
private void SendInfo(string message)
{
#region
//string ip = this.txtip.Text;
//string port = this.txtport.Text;
//IPAddress serverIp = IPAddress.Parse(ip);
//int serverPort = Convert.ToInt32(port);
//IPEndPoint iep = new IPEndPoint(serverIp, serverPort);
//byte[] byteMessage;
//socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//socket.Connect(iep);
#endregion
byte[] byteMessage = Encoding.ASCII.GetBytes(message + "#"); ///x99/x99
socket.Send(byteMessage);
//远端信息
EndPoint tempRemoteEP = socket.RemoteEndPoint;
IPEndPoint tempRemoteIP = (IPEndPoint)tempRemoteEP;
string rempip = tempRemoteIP.Address.ToString();
string remoport = tempRemoteIP.Port.ToString();
//IPHostEntry host = Dns.GetHostByAddress(tempRemoteIP.Address);
IPHostEntry host = Dns.GetHostEntry(tempRemoteIP.Address);
string HostName = host.HostName;
//发送信息
string time1 = DateTime.Now.ToString();
listboxsend.Items.Add("(" + time1 + ") " + HostName + ":");
listboxsend.Items.Add(message);
//发送完了,直接接收
StringBuilder sb = new StringBuilder();
while (true)
{
statusStrip1.Items[1].Text = "正在等待接收信息...";
byte[] bytes = new byte[numbyte];
int recvbytes = socket.Receive(bytes);
string strmsg = Encoding.Default.GetString(bytes);
string time2 = DateTime.Now.ToString();
listboxRecv.Items.Add("(" + time2 + ") " + HostName + ":");
listboxRecv.Items.Add(strmsg);
sb.Append(strmsg);
if (sb.ToString().IndexOf("#") > -1) ///x99/x99
{
break;
}
}
statusStrip1.Items[1].Text = "接收信息完毕!";
//
//代码解码
//CodeParse(sb.ToString());
//
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
}
}
服务器端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets;
namespace GeoMobileServer
{
public partial class FrmAsyncServer : Form
{
public FrmAsyncServer()
{
InitializeComponent();
}
public static ManualResetEvent allDone = new ManualResetEvent(false);
private Thread th;
private bool listenerRun = true;
Socket listener;
private const int MAX_SOCKET = 10;
//得到本机IP地址
public static IPAddress GetServerIP()
{
IPHostEntry ieh = Dns.GetHostByName(Dns.GetHostName());
return ieh.AddressList[0];
}
//侦听方法
private void Listen()
{
try
{
int nPort = int.Parse(this.txtLocalPort.Text);
IPAddress ServerIp = GetServerIP();
IPEndPoint iep = new IPEndPoint(ServerIp, nPort);
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(iep);
listener.Listen(10);
statusStrip1.Items[0].Text = "端口:" + this.txtLocalPort.Text + "正在监听......";
while (listenerRun)
{
allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
allDone.WaitOne();
}
}
catch (System.Security.SecurityException)
{
MessageBox.Show("防火墙安全错误!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
//异步回调函数
public void AcceptCallback(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
Socket client = listener.EndAccept(ar);
allDone.Set();
StateObject state = new StateObject();
state.workSocket = client;
//远端信息
EndPoint tempRemoteEP = client.RemoteEndPoint;
IPEndPoint tempRemoteIP = (IPEndPoint)tempRemoteEP;
string rempip = tempRemoteIP.Address.ToString();
string remoport = tempRemoteIP.Port.ToString();
//IPHostEntry host = Dns.GetHostByAddress(tempRemoteIP.Address);
IPHostEntry host = Dns.GetHostEntry(tempRemoteIP.Address);
string HostName = host.HostName;
statusStrip1.Items[1].Text = "接受[" + HostName + "] " + rempip + ":" + remoport + "远程计算机正确连接!";
string hostInfo = "[" + HostName + "] " + rempip + ":" + remoport;
//this.listboxRemohost.Items.Add("[" + HostName + "] " + rempip + ":" + remoport);
this.listboxRemohost.Invoke(UpdateRemoHost, new object[] { hostInfo });
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(readCallback), state);
}
public delegate void UpdateRemoHostHandler(string hostInfo);
public UpdateRemoHostHandler UpdateRemoHost;
public void UpdateRemoHostMethod(string hostInfo)
{
this.listboxRemohost.Items.Add(hostInfo);
}
public delegate void UpdateReceiveMsgHandler(string time, string hostName, string msg);
public UpdateReceiveMsgHandler UpdateReceiveMsg;
public void UpdateReceiveMsgMethod(string time, string hostName, string msg)
{
this.listboxRecv.Items.Add("(" + time + ") " + hostName + ":");
this.listboxRecv.Items.Add(msg);
}
//异步接收回调函数
public void readCallback(IAsyncResult ar)
{
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
string strmsg = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
state.sb.Append(strmsg);
string content = state.sb.ToString();
//远端信息
EndPoint tempRemoteEP = handler.RemoteEndPoint;
IPEndPoint tempRemoteIP = (IPEndPoint)tempRemoteEP;
string rempip = tempRemoteIP.Address.ToString();
string remoport = tempRemoteIP.Port.ToString();
//IPHostEntry host = Dns.GetHostByAddress(tempRemoteIP.Address);
IPHostEntry host = Dns.GetHostEntry(tempRemoteIP.Address);
string HostName = host.HostName;
statusStrip1.Items[1].Text = "正在接收[" + HostName + "] " + rempip + ":" + remoport + "的信息...";
string time = DateTime.Now.ToString();
//listboxRecv.Items.Add("(" + time + ") " + HostName + ":");
//listboxRecv.Items.Add(strmsg);
this.listboxRecv.Invoke(UpdateReceiveMsg, new object[] { time, HostName, strmsg });
if (content.IndexOf("#") > -1) ///x99/x99
{
statusStrip1.Items[1].Text = "信息接收完毕!";
//
//接收到完整的信息
//MessageBox.Show("接收到:" + content);
//string msg = poweryd.CodeParse(content);
string msg = content;
Send(handler, msg);//异步发送
//Send(content);//用单独的socket发送
}
else
{
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(readCallback), state);
}
}
}
//异步发送
private void Send(Socket handler, String data)
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
//handler.Send(byteData);
}
#region //用单独的socket发送
private void Send(string data)
{
//string ip = this.txtRemoIP.Text;
//string port = this.txtRemoport.Text;
//IPAddress serverIp = IPAddress.Parse(ip);
//int serverPort = Convert.ToInt32(port);
//IPEndPoint iep = new IPEndPoint(serverIp, serverPort);
//Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//socket.Connect(iep);
//byte[] byteMessage = Encoding.ASCII.GetBytes(data);
//socket.Send(byteMessage);
//socket.Shutdown(SocketShutdown.Both);
//socket.Close();
}
#endregion
private void Stop()
{
try
{
listenerRun = false;
th.Abort();
th = null;
listener.Close();
}
catch { }
}
//异步发送回调函数
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket handler = (Socket)ar.AsyncState;
int bytesSent = handler.EndSend(ar);
MessageBox.Show("发送成功!");
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void btnListen_Click(object sender, EventArgs e)
{
th = new Thread(new ThreadStart(Listen));//以Listen过程来初始化线程实例
th.Start();//启动此线程
this.btnListen.Enabled = false;
}
private void btnClosenet_Click(object sender, EventArgs e)
{
try
{
listenerRun = false;
th.Abort();
th = null;
listener.Close();
statusStrip1.Items[0].Text = "与客户端断开连接!";
statusStrip1.Items[1].Text = "";
}
catch
{
MessageBox.Show("连接尚未建立,断开无效!", "警告");
}
}
private void btnExit_Click(object sender, EventArgs e)
{
try
{
listenerRun = false;
th.Abort();
th = null;
listener.Close();
statusStrip1.Items[0].Text = "与客户端断开连接!";
statusStrip1.Items[1].Text = "";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
Application.Exit();
}
}
//异步传递的状态对象
public class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}
private void FrmAsyncServer_Load(object sender, EventArgs e)
{
UpdateRemoHost = new UpdateRemoHostHandler(UpdateRemoHostMethod);
UpdateReceiveMsg = new UpdateReceiveMsgHandler(UpdateReceiveMsgMethod);
}
}
}
代码不用过多解释,最深刻的认识无非是自己单步执行几次,就能了解大概的运作机理了。这里需要注意的一点是因为服务器端采用的是异步执行方式,每收到一个客户端请求,都在服务端后台新建一进程,考虑到进程间的数据安全,是无法直接对主窗体上的UI控件进行调用,这里采用的是通过委托的方式。如下所示:
public delegate void UpdateRemoHostHandler(string hostInfo);
public UpdateRemoHostHandler UpdateRemoHost;
public void UpdateRemoHostMethod(string hostInfo)
{
this.listboxRemohost.Items.Add(hostInfo);
}
而调用的时候,发生了一点小小的变化:
this.listboxRemohost.Invoke(UpdateRemoHost, new object[] { hostInfo });
TCP
Tcp层上主要用到两个对象:TcpListener 类和TcpClient对象。对它们我没有过多的了解,这里粘贴一段msdn上的代码,通过它也能帮助理解个中滋味。
static void Connect(String server, String message)
{
try
{
// Create a TcpClient.
// Note, for this client to work you need to have a TcpServer
// connected to the same address as specified by the server, port
// combination.
Int32 port = 9050;
TcpClient client = new TcpClient(server, port);
// Translate the passed message into ASCII and store it as a Byte array.
Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
// Get a client stream for reading and writing.
// Stream stream = client.GetStream();
NetworkStream stream = client.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}", message);
// Receive the TcpServer.response.
// Buffer to store the response bytes.
data = new Byte[256];
// String to store the response ASCII representation.
String responseData = String.Empty;
// Read the first batch of the TcpServer response bytes.
Int32 bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}", responseData);
//while (true)
//{
// input = Console.ReadLine();//从键盘读取数据
// if (input == "text")//结束标记
// {
// break;
// }
// server.SendTo(Encoding.ASCII.GetBytes(input), Remote);//将数据发送到指定的终结点Remote
// data = new byte[1024];
// recv = server.ReceiveFrom(data, ref Remote);//从Remote接受数据
// stringData = Encoding.ASCII.GetString(data, 0, recv);
// Console.WriteLine(stringData);
//}
// Close everything.
client.Close();
}
catch (ArgumentNullException e)
{
Console.WriteLine("ArgumentNullException: {0}", e);
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
Console.WriteLine("/n Press Enter to continue...");
Console.ReadLine();
}
HttpWebRequest和HttpWebResponse的断背情节
客户端
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://localhost/MobileHttpServer/DataUpload.aspx");
string postData = "TextBox1=" + "aa" + "&TextBox2=" + "bb" + "&TextBox3=" + "cc" + "&TextBox4=" + "dd";
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] byte1 = encoding.GetBytes(postData); //最终编码后要上传的数据
// Set the content type of the data being posted.
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "post"; //post上传方式
// Set the content length of the string being posted.
req.ContentLength = byte1.Length;
Stream newStream = req.GetRequestStream();
newStream.Write(byte1, 0, byte1.Length);
客户端的代码真的很简单,你可以在服务端制作这样一个网页,然后自己在页面的Page_Load事件中看看到底发生了什么鲜为人知的故事,哦,这是秘密,各位看官还是自己动手吧。
如果服务器端返回数据的话,我们可以在客户端用下面的代码进行接收
//在这里对接收到的页面内容进行处理
WebResponse wr = req.GetResponse();
Stream stream = wr.GetResponseStream();
byte[] res = new byte[1024];
int bytesnum = stream.Read(res, 0, res.Length);
string txt = System.Text.UTF8Encoding.Default.GetString(res);
在我的任务计划书中,明确指出需要能够传送图片、声音等各种文件,喔,这时候,首先想到的就是把各种文件序列化成二进制流,然后再发送,不过如果你继续用上面这段代码的话,服务端一点反映都没有,哦,上帝啊,这是什么逻辑,同样是二进制,为什么区别就这么大呢。还好,茫茫大海中总有我们需要的东西可以现成拿来,可以不用让你费劲心机了,通过查看源代码,也能明白一些个中道理。
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
/************************************************************************/
/* 在wwHttp这个类里面,不仅仅可以传送文件AddPostFile方法,还可以传送变量AddPostKey方法。
这样,如果我们要通过代理服务器传送文件,就可以编写如下的代码了:
wwHttp ww = new wwHttp();
ww.ProxyAddress = "202.132.156.124";
ww.PostMode = 2;
ww.AddPostKey("testKey","test");
ww.AddPostFile("myfile",@"D:/Temp/Java/JavaStart/JavaStart2.jar");
string shtml = ww.GetUrlEvents("http://localhost/UploadFileWeb/WebForm1.aspx",409600);
Console.Write(shtml);
小结:
()通过Web Services传文件。
()如果不需要使用代理,使用WebClient类
()如果需要使用代理,使用扩展得到的类wwHttp
/************************************************************************/
namespace HttpWebClient
{
public class wwHttp
{
/// <summary>
/// Fires progress events when using GetUrlEvents() to retrieve a URL.
/// </summary>
public event OnReceiveDataHandler OnReceiveData;
// *** member properties
//string cPostBuffer = "";
MemoryStream oPostStream;
BinaryWriter oPostData;
int nPostMode = 1;
int nConnectTimeout = 30;
string cUserAgent = "West Wind HTTP .NET";
string cUsername = "";
string cPassword = "";
string cProxyAddress = "";
string cProxyBypass = "";
string cProxyUsername = "";
string cProxyPassword = "";
bool bThrowExceptions = false;
bool bHandleCookies = false;
string cErrorMsg = "";
bool bError = false;
HttpWebResponse oWebResponse;
HttpWebRequest oWebRequest;
CookieCollection oCookies;
string cMultiPartBoundary = "-----------------------------7cf 2a 327f 01ae";
/// <summary>
/// Determines how data is POSTed when cPostBuffer is set.
/// 1 - UrlEncoded
/// 2 - Multi-Part form vars
/// 4 - XML (raw buffer content type: text/xml)
/// </summary>
public int PostMode
{
get { return this.nPostMode; }
set { this.nPostMode = value; }
}
/// <summary>
/// User name used for Authentication.
/// To use the currently logged in user when accessing an NTLM resource you can use "AUTOLOGIN".
/// </summary>
public string Username
{
get { return this.cUsername; }
set { cUsername = value; }
}
/// <summary>
/// Password for Authentication.
/// </summary>
public string Password
{
get { return this.cPassword; }
set { this.cPassword = value; }
}
/// <summary>
/// Address of the Proxy Server to be used.
/// Use optional DEFAULTPROXY value to specify that you want to IE's Proxy Settings
/// </summary>
public string ProxyAddress
{
get { return this.cProxyAddress; }
set { this.cProxyAddress = value; }
}
/// <summary>
/// Semicolon separated Address list of the servers the proxy is not used for.
/// </summary>
public string ProxyBypass
{
get { return this.cProxyBypass; }
set { this.cProxyBypass = value; }
}
/// <summary>
/// Username for a password validating Proxy. Only used if the proxy info is set.
/// </summary>
public string ProxyUsername
{
get { return this.cProxyUsername; }
set { this.cProxyUsername = value; }
}
/// <summary>
/// Password for a password validating Proxy. Only used if the proxy info is set.
/// </summary>
public string ProxyPassword
{
get { return this.cProxyPassword; }
set { this.cProxyPassword = value; }
}
/// <summary>
/// Timeout for the Web request in seconds. Times out on connection, read and send operations.
/// Default is 30 seconds.
/// </summary>
public int Timeout
{
get { return this.nConnectTimeout; }
set { this.nConnectTimeout = value; }
}
/// <summary>
/// Error Message if the Error Flag is set or an error value is returned from a method.
/// </summary>
public string ErrorMsg
{
get { return this.cErrorMsg; }
set { this.cErrorMsg = value; }
}
/// <summary>
/// Error flag if an error occurred.
/// </summary>
public bool Error
{
get { return this.bError; }
set { this.bError = value; }
}
/// <summary>
/// Determines whether errors cause exceptions to be thrown. By default errors
/// are handled in the class and the Error property is set for error conditions.
/// (not implemented at this time).
/// </summary>
public bool ThrowExceptions
{
get { return bThrowExceptions; }
set { this.bThrowExceptions = value; }
}
/// <summary>
/// If set to a non-zero value will automatically track cookies. The number assigned is the cookie count.
/// </summary>
public bool HandleCookies
{
get { return this.bHandleCookies; }
set { this.bHandleCookies = value; }
}
public CookieCollection Cookies
{
get { return this.oCookies; }
set { this.Cookies = value; }
}
public HttpWebResponse WebResponse
{
get { return this.oWebResponse; }
set { this.oWebResponse = value; }
}
public HttpWebRequest WebRequest
{
get { return this.oWebRequest; }
set { this.oWebRequest = value; }
}
public void wwHTTP()
{
//
// TODO: Add constructor logic here
//
}
/// <summary>
/// Adds POST form variables to the request buffer.
/// HttpPostMode determines how parms are handled.
/// 1 - UrlEncoded Form Variables. Uses key and value pairs (ie. "Name","Rick") to create URLEncoded content
/// 2 - Multi-Part Forms - not supported
/// 4 - XML block - Post a single XML block. Pass in as Key (1st Parm)
/// other - raw content buffer. Just assign to Key.
/// </summary>
/// <param name="Key">Key value or raw buffer depending on post type</param>
/// <param name="Value">Value to store. Used only in key/value pair modes</param>
public void AddPostKey(string Key, byte[] Value)
{
if (this.oPostData == null)
{
this.oPostStream = new MemoryStream();
this.oPostData = new BinaryWriter(this.oPostStream);
}
if (Key == "RESET")
{
this.oPostStream = new MemoryStream();
this.oPostData = new BinaryWriter(this.oPostStream);
}
switch (this.nPostMode)
{
case 1:
this.oPostData.Write(Encoding.GetEncoding(1252).GetBytes(
Key + "=" + System.Web.HttpUtility.UrlEncode(Value) + "&"));
break;
case 2:
this.oPostData.Write(Encoding.GetEncoding(1252).GetBytes(
"--" + this.cMultiPartBoundary + "/r/n" +
"Content-Disposition: form-data; name=/"" + Key + "/"/r/n/r/n"));
this.oPostData.Write(Value);
this.oPostData.Write(Encoding.GetEncoding(1252).GetBytes("/r/n"));
break;
default:
this.oPostData.Write(Value);
break;
}
}
public void AddPostKey(string Key, string Value)
{
this.AddPostKey(Key, Encoding.GetEncoding(1252).GetBytes(Value));
}
/// <summary>
/// Adds a fully self contained POST buffer to the request.
/// Works for XML or previously encoded content.
/// </summary>
/// <param name="PostBuffer"></param>
public void AddPostKey(string FullPostBuffer)
{
this.oPostData.Write(Encoding.GetEncoding(1252).GetBytes(FullPostBuffer));
}
public bool AddPostFile(string Key, string FileName)
{
byte[] lcFile;
if (this.nPostMode != 2)
{
this.cErrorMsg = "File upload allowed only with Multi-part forms";
this.bError = true;
return false;
}
try
{
FileStream loFile = new FileStream(FileName, System.IO.FileMode.Open, System.IO.FileAccess.Read);
lcFile = new byte[loFile.Length];
loFile.Read(lcFile, 0, (int)loFile.Length);
loFile.Close();
}
catch (Exception e)
{
this.cErrorMsg = e.Message;
this.bError = true;
return false;
}
this.oPostData.Write(Encoding.GetEncoding(1252).GetBytes(
"--" + this.cMultiPartBoundary + "/r/n" +
"Content-Disposition: form-data; name=/"" + Key + "/" filename=/"" +
new FileInfo(FileName).Name + "/"/r/n/r/n"));
this.oPostData.Write(lcFile);
this.oPostData.Write(Encoding.GetEncoding(1252).GetBytes("/r/n"));
return true;
}
/// <summary>
/// Return a the result from an HTTP Url into a StreamReader.
/// Client code should call Close() on the returned object when done reading.
/// </summary>
/// <param name="Url">Url to retrieve.</param>
/// <param name="WebRequest">An HttpWebRequest object that can be passed in with properties preset.</param>
/// <returns></returns>
protected StreamReader GetUrlStream(string Url, HttpWebRequest Request)
{
try
{
this.bError = false;
this.cErrorMsg = "";
if (Request == null)
Request = (HttpWebRequest)System.Net.WebRequest.Create(Url);
Request.UserAgent = this.cUserAgent;
Request.Timeout = this.nConnectTimeout * 1000;
// *** Save for external access
this.oWebRequest = Request;
// *** Handle Security for the request
if (this.cUsername.Length > 0)
if (this.cUsername == "AUTOLOGIN")
Request.Credentials = CredentialCache.DefaultCredentials;
else
Request.Credentials = new NetworkCredential(this.cUsername, this.cPassword);
// *** Handle Proxy Server configuration
if (this.cProxyAddress.Length > 0)
{
if (this.cProxyAddress == "DEFAULTPROXY")
{
Request.Proxy = new WebProxy();
Request.Proxy = WebProxy.GetDefaultProxy();
}
else
{
WebProxy loProxy = new WebProxy(this.cProxyAddress, true);
if (this.cProxyBypass.Length > 0)
{
loProxy.BypassList = this.cProxyBypass.Split(';');
}
if (this.cProxyUsername.Length > 0)
loProxy.Credentials = new NetworkCredential(this.cProxyUsername, this.cProxyPassword);
Request.Proxy = loProxy;
}
}
// *** Handle cookies - automatically re-assign
if (this.bHandleCookies)
{
Request.CookieContainer = new CookieContainer();
if (this.oCookies != null && this.oCookies.Count > 0)
{
Request.CookieContainer.Add(this.oCookies);
}
}
// *** Deal with the POST buffer if any
if (this.oPostData != null)
{
Request.Method = "POST";
switch (this.nPostMode)
{
case 1:
Request.ContentType = "application/x-www-form-urlencoded";
// strip off any trailing & which can cause problems with some
// http servers
// if (this.cPostBuffer.EndsWith("&"))
// this.cPostBuffer = this.cPostBuffer.Substring(0,this.cPostBuffer.Length-1);
break;
case 2:
Request.ContentType = "multipart/form-data; boundary=" + this.cMultiPartBoundary;
this.oPostData.Write(Encoding.GetEncoding(1252).GetBytes("--" + this.cMultiPartBoundary + "/r/n"));
break;
case 4:
Request.ContentType = "text/xml";
break;
default:
goto case 1;
}
Stream loPostData = Request.GetRequestStream();
//loPostData.Write(lcPostData,0,lcPostData.Length);
this.oPostStream.WriteTo(loPostData);
byte[] buffer = new byte[this.oPostStream.Length];
buffer = this.oPostStream.ToArray();
//Console.Write(Encoding.GetEncoding(1252).GetString(buffer, 0, buffer.Length));
//*** Close the memory stream
this.oPostStream.Close();
this.oPostStream = null;
//*** Close the Binary Writer
this.oPostData.Close();
this.oPostData = null;
//*** Close Request Stream
loPostData.Close();
// *** clear the POST buffer
//this.cPostBuffer = "";
}
// *** Retrieve the response headers
HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();
// ** Save cookies the server sends
if (this.bHandleCookies)
{
if (Response.Cookies.Count > 0)
{
if (this.oCookies == null)
{
this.oCookies = Response.Cookies;
}
else
{
// ** If we already have cookies update the list
foreach (Cookie oRespCookie in Response.Cookies)
{
bool bMatch = false;
foreach (Cookie oReqCookie in this.oCookies)
{
if (oReqCookie.Name == oRespCookie.Name)
{
oReqCookie.Value = oRespCookie.Name;
bMatch = true;
break; //
}
} // for each ReqCookies
if (!bMatch)
this.oCookies.Add(oRespCookie);
} // for each Response.Cookies
} // this.Cookies == null
} // if Response.Cookie.Count > 0
} // if this.bHandleCookies = 0
// *** Save the response object for external access
this.oWebResponse = Response;
Encoding enc;
try
{
if (Response.ContentEncoding.Length > 0)
enc = Encoding.GetEncoding(Response.ContentEncoding);
else
enc = Encoding.GetEncoding(1252);
}
catch
{
// *** Invalid encoding passed
enc = Encoding.GetEncoding(1252);
}
// *** drag to a stream
StreamReader strResponse = new StreamReader(Response.GetResponseStream(), enc);
return strResponse;
}
catch (Exception e)
{
if (this.bThrowExceptions)
throw e;
this.cErrorMsg = e.Message;
this.bError = true;
return null;
}
}
/// <summary>
/// Return a the result from an HTTP Url into a StreamReader.
/// Client code should call Close() on the returned object when done reading.
/// </summary>
/// <param name="Url">Url to retrieve.</param>
/// <returns></returns>
public StreamReader GetUrlStream(string Url)
{
HttpWebRequest oHttpWebRequest = null;
return this.GetUrlStream(Url, oHttpWebRequest);
}
/// <summary>
/// Return a the result from an HTTP Url into a StreamReader.
/// Client code should call Close() on the returned object when done reading.
/// </summary>
/// <param name="Request">A Request object</param>
/// <returns></returns>
public StreamReader GetUrlStream(HttpWebRequest Request)
{
return this.GetUrlStream(Request.RequestUri.AbsoluteUri, Request);
}
/// <summary>
/// Return a the result from an HTTP Url into a string.
/// </summary>
/// <param name="Url">Url to retrieve.</param>
/// <returns></returns>
public string GetUrl(string Url)
{
StreamReader oHttpResponse = this.GetUrlStream(Url);
if (oHttpResponse == null)
return "";
string lcResult = oHttpResponse.ReadToEnd();
oHttpResponse.Close();
return lcResult;
}
/// <summary>
/// Return a the result from an HTTP Url into a string.
/// </summary>
/// <param name="Url">Url to retrieve.</param>
/// <returns></returns>
public byte[] GetUrlBytes(string Url)
{
StreamReader oHttpResponse = this.GetUrlStream(Url);
if (oHttpResponse == null)
{
return null;
}
string lcResult = oHttpResponse.ReadToEnd();
oHttpResponse.Close();
return null;
}
/// <summary>
/// Retrieves URL with events in the OnReceiveData event.
/// </summary>
/// <param name="Url"></param>
/// <param name="BufferSize"></param>
/// <returns></returns>
public string GetUrlEvents(string Url, long BufferSize)
{
StreamReader oHttpResponse = this.GetUrlStream(Url);
if (oHttpResponse == null)
return "";
long lnSize = BufferSize;
if (this.oWebResponse.ContentLength > 0)
lnSize = this.oWebResponse.ContentLength;
else
lnSize = 0;
Encoding enc = Encoding.GetEncoding(1252);
StringBuilder loWriter = new StringBuilder((int)lnSize);
char[] lcTemp = new char[BufferSize];
OnReceiveDataEventArgs oArgs = new OnReceiveDataEventArgs();
oArgs.TotalBytes = lnSize;
lnSize = 1;
int lnCount = 0;
long lnTotalBytes = 0;
while (lnSize > 0)
{
lnSize = oHttpResponse.Read(lcTemp, 0, (int)BufferSize);
if (lnSize > 0)
{
loWriter.Append(lcTemp, 0, (int)lnSize);
lnCount++;
lnTotalBytes += lnSize;
// *** Raise an event if hooked up
if (this.OnReceiveData != null)
{
/// *** Update the event handler
oArgs.CurrentByteCount = lnTotalBytes;
oArgs.NumberOfReads = lnCount;
oArgs.CurrentChunk = lcTemp;
this.OnReceiveData(this, oArgs);
// *** Check for cancelled flag
if (oArgs.Cancel)
goto CloseDown;
}
}
} // while
CloseDown:
oHttpResponse.Close();
// *** Send Done notification
if (this.OnReceiveData != null && !oArgs.Cancel)
{
// *** Update the event handler
oArgs.Done = true;
this.OnReceiveData(this, oArgs);
}
// return lcHtml;
return loWriter.ToString();
}
public delegate void OnReceiveDataHandler(object sender, OnReceiveDataEventArgs e);
public class OnReceiveDataEventArgs
{
public long CurrentByteCount = 0;
public long TotalBytes = 0;
public int NumberOfReads = 0;
public char[] CurrentChunk;
public bool Done = false;
public bool Cancel = false;
}
}
}
其实微软有一个现成的类:WebClient可以实现文件上传等功能,不过这个类在NETCF下不受支持,没办法,只好采用替代品了,还好有人替我们完成了这样的工作J
微软的消息队列(MSMQ)
这个就暂时不说了,涉及的内容较多,留待以后单独进行说明。