客户端的实现


与服务端类似,我们首先对 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开发框架网发布内容,转载请附上原文出处连接
张国生
上一篇:服务端实现
下一篇:程序测试
评论列表

发表评论

评论内容
昵称:
关联文章

客户实现
客户接收文件
客户发送数据
服务实现
服务获取客户连接
2.客户与服务连接
FTP客户工具 FileZilla
ABP VNext框架中Winform终端开发和客户授权信息处理
客户发送,服务接收并输出
FTP客户工具 WinSCP ( 推荐,免费 )
服务回发,客户接收并输出
FTP客户工具 FlashFXP (推荐)
GZUpdate自动升级程序客户演示
网易闪电邮客户中配置企业邮箱方法
GZUpdate自动升级服务 .NET C/S Winform客户程序自动升级演示
协议处理类实现
有限在线用户场景中,前后分离是多此一举
FTP服务软件 Xlight
使用.NET 6开发TodoList应用(27)——实现APISwagger文档化
Blazor Webassembly多标签页实现非iframe实现