客户端的实现
与服务端类似,我们首先对 TcpClient 进行一个简单的包装,使它的使用更加方便一些,因为它是服务端的客户,所以我们将类的名称 命名为 ServerClient:
public class ServerClient {
private const int BufferSize = 8192;
private byte[] buffer;
private TcpClient client;
private NetworkStream streamToServer;
private string msg = "Welcome to TraceFact.Net!";
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) {
msg = String.Format("[length={0}]{1}", msg.Length, msg);
for (int i = 0; i <= 2; i++) {
byte[] temp = Encoding.Unicode.GetBytes(msg); // 获得缓存
try {
streamToServer.Write(temp, 0, temp.Length); // 发往服务器
Console.WriteLine("Sent: {0}", msg);
} catch (Exception ex) {
Console.WriteLine(ex.Message);
break;
}
}
lock (streamToServer) {
AsyncCallback callBack = new AsyncCallback(ReadComplete);
streamToServer.BeginRead(buffer, 0, BufferSize, callBack, null);
}
}
public void SendMessage() {
SendMessage(this.msg);
}
// 读取完成时的回调方法
private void ReadComplete(IAsyncResult ar) {
int bytesRead;
try {
lock (streamToServer) {
bytesRead = streamToServer.EndRead(ar);
}
if (bytesRead == 0) throw new Exception("读取到 0 字节");
string msg = Encoding.Unicode.GetString(buffer, 0, bytesRead);
Console.WriteLine("Received: {0}", msg);
Array.Clear(buffer, 0, buffer.Length); // 清空缓存,避免脏读
lock (streamToServer) {
AsyncCallback callBack = new AsyncCallback(ReadComplete);
streamToServer.BeginRead(buffer, 0, BufferSize, callBack, null);
}
} catch (Exception ex) {
if(streamToServer!=null)
streamToServer.Dispose();
client.Close();
Console.WriteLine(ex.Message);
}
}
}
在上面的 SendMessage()方法中,我们让它连续发送了三条同样的消息,这么仅仅是为了测试,因为异步操作同样会出现上面说过的: 服务器将 客户端的请求拆开了的情况。最后我们在 Main()方法中创建这个类型的实例,然后调用 SendMessage()方法进行测试:
class Client {
static void Main(string[] args) {
ConsoleKey key;
ServerClient client = new ServerClient();
client.SendMessage();
Console.WriteLine("\n\n 输入\"Q\"键退出。");
do {
key = Console.ReadKey(true).Key;
} while (key != ConsoleKey.Q);
}
}
是不是感觉很清爽?因为良好的代码重构,使得程序在复杂程度提高的情况下依然可以在一定程度上保持良好的阅读性。
版权声明:本文为YES开发框架网发布内容,转载请附上原文出处连接
Socket 张国生