C#网络编程(订立协议和发送文件) - Part.4
2009-03-26 08:22:21 来源:WEB开发网这里应该没有什么新知识,需要注意的地方有这么几个:
在OnReadComplete()回调方法中的foreach循环,我们使用委托异步调用了handleProtocol()方法,这是因为handleProtocol即将执行的是一个读取或接收文件的操作,也就是一个相对耗时的操作。
在handleProtocol()方法中,我们深切体会了定义ProtocolHelper类和FileProtocol结构的好处。如果没有定义它们,这里将是不堪入目的处理XML以及类型转换的代码。
handleProtocol()方法中进行了一个条件判断,注意sendFile()方法我屏蔽掉了,这个还没有实现,但是我想你已经猜到它将是后面要实现的内容。
receiveFile()方法是实际接收客户端发来文件的方法,这里没有什么特别之处。需要注意的是文件存储的路径,它保存在了当前程序执行的目录下,文件的名称我使用generateFileName()生成了一个与时间有关的随机名称。
3.2客户端的实现
我们现在先不着急实现客户端S1、R1等用户菜单,首先完成发送文件这一功能,实际上,就是为上一节SendMessage()加一个姐妹方法SendFile()。
class Client {
static void
Main(string[] args) {
ConsoleKey key;
ServerClient client = new ServerClient();
string filePath = Environment.CurrentDirectory + "/" + "Client01.jpg";
if(File.Exists(filePath))
client.BeginSendFile(filePath);
Console.WriteLine("nn输入"Q"键退出。");
do {
key = Console.ReadKey(true).Key;
} while (key != ConsoleKey.Q);
}
}
public class ServerClient {
private const int BufferSize = 8192;
private byte[] buffer;
private TcpClient client;
private NetworkStream streamToServer;
public ServerClient() {
try {
client = new TcpClient();
client.Connect("localhost", 8500); // 与服务器连接
} catch (Exception ex) {
Console.WriteLine(ex.Message);
return;
}
buffer = new byte[BufferSize];
// 打印连接到的服务端信息
Console.WriteLine("Server Connected!{0} --> {1}",
client.Client.LocalEndPoint, client.Client.RemoteEndPoint);
streamToServer = client.GetStream();
}
// 发送消息到服务端
public void SendMessage(string msg) {
byte[] temp = Encoding.Unicode.GetBytes(msg); // 获得缓存
try {
lock (streamToServer) {
streamToServer.Write(temp, 0, temp.Length); // 发往服务器
}
Console.WriteLine("Sent: {0}", msg);
} catch (Exception ex) {
Console.WriteLine(ex.Message);
return;
}
}
// 发送文件 - 异步方法
public void BeginSendFile(string filePath) {
ParameterizedThreadStart start =
new ParameterizedThreadStart(BeginSendFile);
start.BeginInvoke(filePath, null, null);
}
private void BeginSendFile(object obj) {
string filePath = obj as string;
SendFile(filePath);
}
// 发送文件 -- 同步方法
public void SendFile(string filePath) {
IPAddress ip = IPAddress.Parse("127.0.0.1");
TcpListener listener = new TcpListener(ip, 0);
listener.Start();
// 获取本地侦听的端口号
IPEndPoint endPoint = listener.LocalEndpoint as IPEndPoint;
int listeningPort = endPoint.Port;
// 获取发送的协议字符串
string fileName = Path.GetFileName(filePath);
FileProtocol protocol =
new FileProtocol(FileRequestMode.Send, listeningPort, fileName);
string pro = protocol.ToString();
SendMessage(pro); // 发送协议到服务端
// 中断,等待远程连接
TcpClient localClient = listener.AcceptTcpClient();
Console.WriteLine("Start sending file...");
NetworkStream stream = localClient.GetStream();
// 创建文件流
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
byte[] fileBuffer = new byte[1024]; // 每次传1KB
int bytesRead;
int totalBytes = 0;
// 创建获取文件发送状态的类
SendStatus status = new SendStatus(filePath);
// 将文件流转写入网络流
try {
do {
Thread.Sleep(10); // 为了更好的视觉效果,暂停10毫秒:-)
bytesRead = fs.Read(fileBuffer, 0, fileBuffer.Length);
stream.Write(fileBuffer, 0, bytesRead);
totalBytes += bytesRead; // 发送了的字节数
status.PrintStatus(totalBytes); // 打印发送状态
} while (bytesRead > 0);
Console.WriteLine("Total {0} bytes sent, Done!", totalBytes);
} catch {
Console.WriteLine("Server has lost...");
}
stream.Dispose();
fs.Dispose();
localClient.Close();
listener.Stop();
}
}
更多精彩
赞助商链接