C#网络编程(订立协议和发送文件) - Part.4
2009-03-26 08:22:21 来源:WEB开发网OK,我们又耽误了点时间,下面就让我们进入正题吧。
3.客户端发送数据
3.1 服务端的实现
我们还是将一个问题分成两部分来处理,先是发送数据,然后是接收数据。我们先看发送数据部分的服务端。如果你从第一篇文章看到了现在,那么我觉得更多的不是技术上的问题而是思路,所以我们不再将重点放到代码上,这些应该很容易就看懂了。
class Server {
static void
Main(string[] args) {
Console.WriteLine("Server is running ... ");
IPAddress ip = IPAddress.Parse("127.0.0.1");
TcpListener listener = new TcpListener(ip, 8500);
listener.Start(); // 开启对控制端口 8500 的侦听
Console.WriteLine("Start Listening ...");
while (true) {
// 获取一个连接,同步方法,在此处中断
TcpClient client = listener.AcceptTcpClient();
RemoteClient wapper = new RemoteClient(client);
wapper.BeginRead();
}
}
}
public class RemoteClient {
private TcpClient client;
private NetworkStream streamToClient;
private const int BufferSize = 8192;
private byte[] buffer;
private ProtocolHandler handler;
public RemoteClient(TcpClient client) {
this.client = client;
// 打印连接到的客户端信息
Console.WriteLine("nClient Connected!{0} <-- {1}",
client.Client.LocalEndPoint, client.Client.RemoteEndPoint);
// 获得流
streamToClient = client.GetStream();
buffer = new byte[BufferSize];
handler = new ProtocolHandler();
}
// 开始进行读取
public void BeginRead() {
AsyncCallback callBack = new AsyncCallback(OnReadComplete);
streamToClient.BeginRead(buffer, 0, BufferSize, callBack, null);
}
// 再读取完成时进行回调
private void OnReadComplete(IAsyncResult ar) {
int bytesRead = 0;
try {
lock (streamToClient) {
bytesRead = streamToClient.EndRead(ar);
Console.WriteLine("
Reading data, {0} bytes ...", bytesRead);
}
if (bytesRead == 0) throw new Exception("读取到0字节");
string msg = Encoding.Unicode.GetString(buffer, 0, bytesRead);
Array.Clear(buffer,0,buffer.Length); // 清空缓存,避免脏读
// 获取protocol数组
string[] protocolArray = handler.GetProtocol(msg);
foreach (string pro in protocolArray) {
// 这里异步调用,不然这里可能会比较耗时
ParameterizedThreadStart start =
new ParameterizedThreadStart(handleProtocol);
start.BeginInvoke(pro, null, null);
}
// 再次调用BeginRead(),完成时调用自身,形成无限循环
lock (streamToClient) {
AsyncCallback callBack = new AsyncCallback(OnReadComplete);
streamToClient.BeginRead(buffer, 0, BufferSize, callBack, null);
}
} catch(Exception ex) {
if(streamToClient!=null)
streamToClient.Dispose();
client.Close();
Console.WriteLine(ex.Message); // 捕获异常时退出程序
}
}
// 处理protocol
private void handleProtocol(object obj) {
string pro = obj as string;
ProtocolHelper helper = new ProtocolHelper(pro);
FileProtocol protocol = helper.GetProtocol();
if (protocol.Mode == FileRequestMode.Send) {
// 客户端发送文件,对服务端来说则是接收文件
receiveFile(protocol);
} else if (protocol.Mode == FileRequestMode.Receive) {
// 客户端接收文件,对服务端来说则是发送文件
// sendFile(protocol);
}
}
private void receiveFile(FileProtocol protocol) {
// 获取远程客户端的位置
IPEndPoint endpoint = client.Client.RemoteEndPoint as IPEndPoint;
IPAddress ip = endpoint.Address;
// 使用新端口号,获得远程用于接收文件的端口
endpoint = new IPEndPoint(ip, protocol.Port);
// 连接到远程客户端
TcpClient localClient;
try {
localClient = new TcpClient();
localClient.Connect(endpoint);
} catch {
Console.WriteLine("无法连接到客户端 --> {0}", endpoint);
return;
}
// 获取发送文件的流
NetworkStream streamToClient = localClient.GetStream();
// 随机生成一个在当前目录下的文件名称
string path =
Environment.CurrentDirectory + "/" + generateFileName(protocol.FileName);
byte[] fileBuffer = new byte[1024]; // 每次收1KB
FileStream fs = new FileStream(path, FileMode.CreateNew, FileAccess.Write);
// 从缓存buffer中读入到文件流中
int bytesRead;
int totalBytes = 0;
do {
bytesRead = streamToClient.Read(buffer, 0, BufferSize);
fs.Write(buffer, 0, bytesRead);
totalBytes += bytesRead;
Console.WriteLine("Receiving {0} bytes ...", totalBytes);
} while (bytesRead > 0);
Console.WriteLine("Total {0} bytes received, Done!", totalBytes);
streamToClient.Dispose();
fs.Dispose();
localClient.Close();
}
// 随机获取一个图片名称
private string generateFileName(string fileName) {
DateTime now = DateTime.Now;
return String.Format(
"{0}_{1}_{2}_{3}", now.Minute, now.Second, now.Millisecond, fileName
);
}
}
更多精彩
赞助商链接