C#异步套接字/多线程:我使用异步套接字和正确线程?

我读过许多教程,并在C#异步插座其他页面。 我需要写一个TCP客户端,可以在同一时间进行阅读和写作。 这就是为什么我选择了异步插座。 这里是代码。 我使用异步套接字和正确线程?

using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading; namespace WindowsFormsApplication2 { public delegate void ConnectEventHandler(object sender, ConnectEventArgs e); // More similar delegates defined for each event to pass to the GUI thread... public class Client { bool m_MasterSwitch; ArrayList m_ProductList; public event ConnectEventHandler ConnectEvent = delegate { }; Socket m_Socket; EventWaitHandle m_WaitHandle; readonly object m_Locker; Queue<IEvent> m_Tasks; Thread m_Thread; public Client() { m_MasterSwitch = false; m_ProductList = new ArrayList(); m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); m_WaitHandle = new AutoResetEvent(false); m_Locker = new object(); m_Tasks = new Queue<IEvent>(); m_Thread = new Thread(Run); m_Thread.IsBackground = true; m_Thread.Start(); } public void EnqueueTask(IEvent task) { lock (m_Locker) { m_Tasks.Enqueue(task); } m_WaitHandle.Set(); } private void Run() { while (true) { m_WaitHandle.WaitOne(); IEvent task = null; lock (m_Locker) { if (m_Tasks.Count == 0) { m_WaitHandle.Reset(); continue; } task = m_Tasks.Dequeue(); } if (task == null) { return; } else { task.DoTask(this); } } } public void Connect(string hostname, int port) { try { IPAddress[] IPs = Dns.GetHostAddresses(hostname); m_Socket.BeginConnect(IPs, port, new AsyncCallback(ConnectCallback), m_Socket); } catch (Exception) { OnConnect(false, "Unable to connect to server."); } } private void ConnectCallback(IAsyncResult ar) { try { Socket socket = (Socket)ar.AsyncState; socket.EndConnect(ar); OnConnect(true, "Successfully connected to server."); StartRead(socket); } catch (Exception) { OnConnect(false, "Unable to connect to server."); } } private void StartRead(Socket socket) { StateObject state = new StateObject(); state.AsyncSocket = socket; socket.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state); } private void ReceiveCallback(IAsyncResult ar) { try { StateObject state = (StateObject)ar.AsyncState; int bytes_read = state.AsyncSocket.EndReceive(ar); char[] chars = new char[bytes_read + 1]; System.Text.Decoder decoder = System.Text.Encoding.UTF8.GetDecoder(); int charLength = decoder.GetChars(state.Buffer, 0, bytes_read, chars, 0); String data = new String(chars); ParseMessage(data); StartRead(state.AsyncSocket); } catch (ObjectDisposedException) { } catch (SocketException) { } } private void StartSend(string message) { try { StateObject state = new StateObject(); state.AsyncSocket = m_Socket; byte[] buffer = Encoding.UTF8.GetBytes(message); m_Socket.BeginSend(buffer, 0, buffer.Length, 0, new AsyncCallback(SendCallback), state); } catch (Exception) { } } private void SendCallback(IAsyncResult ar) { try { StateObject state = (StateObject)ar.AsyncState; state.AsyncSocket.EndSend(ar); } catch { } } private void ParseMessage(string data) { string[] messages = data.Split('\n'); foreach (string message in messages) { if (message != "") { string[] tokens = message.Split(','); string command = tokens[0]; switch (command) { case "@1": { string exchangeName = tokens[1]; string connectionStatus = tokens[2]; string loggedInStatus = tokens[3]; bool connectionStatusBool; bool loggedInStatusBool; if (connectionStatus == "1") { connectionStatusBool = true; } else { connectionStatusBool = false; } if (loggedInStatus == "1") { loggedInStatusBool = true; } else { loggedInStatusBool = false; } OnExchangeStatusMessage(exchangeName, connectionStatusBool, loggedInStatusBool); break; } case "@2": { string isError = tokens[1]; string logMessage = tokens[2]; bool isErrorBool; if (isError == "error") { isErrorBool = true; } else { isErrorBool = false; } OnLogMessage(isErrorBool, logMessage); break; } case "@3": { OnLogMessage(false, message); break; } case "@4": { string masterSwitch = tokens[1]; if (masterSwitch == "1") { m_MasterSwitch = true; } else { m_MasterSwitch = false; } m_ProductList.Clear(); for (int i = 2; i < tokens.Length; ++i) { string[] productArray = tokens[i].Split('='); if (productArray.Length < 2) { break; } string name = productArray[0]; string isLive = productArray[1]; bool isLiveBool; if (isLive == "1") { isLiveBool = true; } else { isLiveBool = false; } m_ProductList.Add(new Product(name, isLiveBool)); } OnLiveMessage(m_MasterSwitch, m_ProductList); break; } default: break; } } } } public void SetLiveStatus() { bool newState = (! m_MasterSwitch); string newStateString; if (newState) { newStateString = "1"; } else { newStateString = "0"; } StartSend(String.Format("@4,{0}\n", newStateString)); } public void SetProductLiveStatus(Product product) { if (m_ProductList.Contains(product)) { string masterSwitchString; if (m_MasterSwitch) { masterSwitchString = "1"; } else { masterSwitchString = "0"; } bool newState = (! product.IsLive); string newStateString; if (newState) { newStateString = "1"; } else { newStateString = "0"; } StartSend(String.Format("@4,{0},{1}={2}\n", masterSwitchString, product.Name, newStateString)); } } private void OnConnect(bool isConnected, string message) { ConnectEvent(this, new ConnectEventArgs(isConnected, message)); } // More events to pass to the GUI... } }

--------------解决方案-------------

正如其他人所指出的,有很多的代码去。 但是,仅仅从快速阅读...

  1. 你失踪的消息帧。
  2. 你忽略的返回值EndSend 。 这可能是部分发送就可以完成,你就会有发送数据的其余部分。

有很多的代码在这里,它不会编译,所以我不能运行它或对它进行测试。 我有代码审查代码的基础上如何异步套接字代码通常是书面上和精神上执行的代码,看看我认为这是可行的。

所以,做我认为它会工作? 我不知道。 它的工作原理? 你已经运行呢? 如果我说没关系,它不工作,那么因为也许我忽视了你的代码的东西很明显我会觉得愚蠢。

但是,对于一个简单的“眼里只有”代码审查,我可以说,是的,你似乎是使用它的目的是使用方式的范围内的aysnc套接字API。 有迹象表明,我会做不同,但是这不是你的问题,许多文体的事情。

但是,即使你有一个良好的基础异步设计,很多事情都可能出错在执行。该客户机/服务器仍然需要被整合到一个应用程序,许多异步设计问题关键取决于这种关系。

只有你可以编译,运行,调试和测试程序。 在这样做的过程中,如果你碰上,让你怀疑你的异步设计是有缺陷的一个具体问题,尽量浓缩为一个小的测试案例,然后回来,我们会看到,如果我们可以提供帮助。

分类:C# 时间:2015-03-15 人气:0
本文关键词: 多线程,插座
分享到:

相关文章

Copyright (C) 55228885.com, All Rights Reserved.

55228885 版权所有 京ICP备15002868号

processed in 0.279 (s). 10 q(s)