套接字编程

好吧,我已经绞尽脑汁,无法找到解决方案。 这里的问题是我能够调用begin-receive一次,但之后我无法找到一种适当的技术,可以一次又一次地调用该方法。 因此,虽然正在建立连接,但消息可以只接收一次,之后不再接收..请帮助,因为它非常紧急。谢谢你。 我在这里放下整个代码。

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; using System.IO; using.System.Threading; namespace WindowsApplication1 { public partial class lanmessenger : Form { Socket client; Socket newSock, server, hostSock, remote; byte[] receiveBuffer = new byte[1024]; byte[] sendBuffer = new byte[1024]; String dataEntered; StringBuilder textbox1, receivedData, sb; IPEndPoint serverIP, clientIP; [DllImport("user32.dll")] static extern bool HideCaret(IntPtr hWnd); Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress localaddress = IPAddress.Parse("127.0.0.1"); public void Receive() { if (remote.Connected) remote.BeginReceive(receiveBuffer, 0, receiveBuffer.Length, System.Net.Sockets.SocketFlags.None, new AsyncCallback(OnReceivingData), remote); else return; } void OnReceivingData(IAsyncResult ar) { remote = (Socket)ar.AsyncState; int recv = remote.EndReceive(ar); receivedData = new StringBuilder(Encoding.ASCII.GetString(receiveBuffer, 0, recv)); //MessageBox.Show(receivedData.ToString(), "received", MessageBoxButtons.OK); sb = new StringBuilder(this.textBox1.Text); sb.AppendLine(receivedData.ToString()); if (textBox1.InvokeRequired) { this.Invoke((MethodInvoker)delegate { this.textBox1.Text = sb.ToString(); }); } //Receive(); return; } private void Accepted(IAsyncResult ar) { server = (Socket)ar.AsyncState; client = server.EndAccept(ar); /*if (client.Connected) MessageBox.Show("client connected");*/ try { client.BeginReceive(receiveBuffer, 0, receiveBuffer.Length, System.Net.Sockets.SocketFlags.None, new AsyncCallback(OnReceivingData), client); } catch (ArgumentException) { MessageBox.Show("arguments incorrect in begin-receive call", "Error", MessageBoxButtons.OK); } catch (SocketException) { MessageBox.Show("error in accessing socket while receiving", "Error", MessageBoxButtons.OK); } catch (ObjectDisposedException) { MessageBox.Show("socket closed while receiving", "Error", MessageBoxButtons.OK); } catch (Exception) { MessageBox.Show("error while receiving", "Error", MessageBoxButtons.OK); } } public void FirstEndPoint() { newSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); clientIP = new IPEndPoint(localaddress, 5555); newSock.Bind(clientIP); newSock.Listen(100); try { newSock.BeginAccept(new AsyncCallback(Accepted), newSock); } catch (ArgumentException) { MessageBox.Show("Error in arguments while using begin-accept", "Error", MessageBoxButtons.OK); } catch (ObjectDisposedException) { MessageBox.Show("socket closed while using begin-accept", "Error", MessageBoxButtons.OK); } catch (SocketException) { MessageBox.Show("Error accessing socket while using begin-accept", "Error", MessageBoxButtons.OK); } catch (InvalidOperationException) { MessageBox.Show("Invalid operation while using begin-accept", "Error", MessageBoxButtons.OK); } catch (Exception) { MessageBox.Show("Exception occurred while using begin-accept", "Error", MessageBoxButtons.OK); } } public void CreateThread() { Thread FirstThread = new Thread(new ThreadStart(FirstEndPoint)); FirstThread.Start(); } public lanmessenger() { InitializeComponent(); CreateThread(); } void OnSendingData(IAsyncResult ar) { Socket socket = (Socket)ar.AsyncState; int AmtOfData = socket.EndSend(ar); //MessageBox.Show(AmtOfData.ToString()); return; } public void SendingData(Socket sock, String data) { textbox1.AppendLine(this.textBox2.Text); if (textBox1.InvokeRequired) { this.Invoke((MethodInvoker)delegate { this.textBox1.Text = textbox1.ToString(); }); } if (textBox2.InvokeRequired) { this.Invoke((MethodInvoker)delegate { this.textBox2.Text = "\0"; }); } sendBuffer = Encoding.ASCII.GetBytes(data); try { sock.BeginSend(sendBuffer, 0, sendBuffer.Length, SocketFlags.None, new AsyncCallback(OnSendingData), sock); } catch (ArgumentException) { MessageBox.Show("arguments incorrect in begin-send call", "Error", MessageBoxButtons.OK); } catch (SocketException ex) { String str1 = "error in accessing socket while sending" + ex.ErrorCode.ToString(); MessageBox.Show(str1, "Error", MessageBoxButtons.OK); } catch (ObjectDisposedException) { MessageBox.Show("socket closed while sending", "Error", MessageBoxButtons.OK); } catch (Exception) { MessageBox.Show("error while sending", "Error", MessageBoxButtons.OK); } } private void OnClientConnect(IAsyncResult ar) { Socket sock = (Socket)ar.AsyncState; try { sock.EndConnect(ar); if (sock.Connected) MessageBox.Show("connected"); } catch (SocketException ex) { MessageBox.Show("Error in accessing socket while using end-connect" + ex.ErrorCode.ToString(), "Error", MessageBoxButtons.OK); return; } if ((sock.Connected) && (dataEntered != "")) { SendingData(sock, dataEntered); } } private void button1_Click(object sender, EventArgs e) { HideCaret(this.textBox1.Handle); textbox1 = new StringBuilder(this.textBox1.Text); dataEntered = this.textBox2.Text; hostSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); serverIP = new IPEndPoint(localaddress, 5555); try { hostSock.BeginConnect(serverIP, new AsyncCallback(OnClientConnect), hostSock); } catch (ArgumentException) { MessageBox.Show("Error in arguments while using begin-connect", "Error", MessageBoxButtons.OK); return; } catch (SocketException) { MessageBox.Show("Error in accessing socket while using begin-connect", "Error", MessageBoxButtons.OK); return; } catch (ObjectDisposedException) { MessageBox.Show("socket closed while using begin-connect", "Error", MessageBoxButtons.OK); return; } catch (InvalidOperationException) { MessageBox.Show("Invalid operation while using begin-connect", "Error", MessageBoxButtons.OK); return; } catch (Exception) { MessageBox.Show("Exception while using begin-connect", "Error", MessageBoxButtons.OK); return; } } } 

}

首先,您可能希望使用一些更合适的标记来标记您的问题。 此外 – 由于这是从MSDN文档中提取的异步TCP客户端消息传递,您可能需要再次参考您的文档。

(在本地VS帮助URL中: MSDN异步客户端套接字示例 )

您没有提到为什么在回调方法中启动新的异步接收操作失败 – 您看到了什么错误?

如果您的消息已成功接收并在异步回调中处理,则可以从那里再次呼叫您的接收(已注释掉)。 请记住,如果重用状态对象(在您的情况下为远程),则需要清除缓冲区和其中持久存在的任何其他对象。

在Receive方法中,您应该初始化状态对象并为新的异步接收操作再次准备它。

另外:我之前使用的接收回调。 其中一些是特定于我正在处理的应用程序(例如将消息排入基类中,这是从中派生出来的),它相当快速和肮脏,但它可能会有所帮助。

  private void ReceiveCallback(IAsyncResult ar) { int bytesRead = 0; try { // receive finished if (ar.IsCompleted) { TcpIpState stateObject = (TcpIpState)ar.AsyncState; bytesRead = stateObject.TcpIpSocket.EndReceive(ar, out seSocketError); if (bytesRead > 0) { foreach (ArraySegment asBuffer in stateObject.Buffer) { stateObject.SBuilder.Append( Encoding.ASCII.GetChars( asBuffer.Array, 0, asBuffer.Count)); } // Let the owner object know of the received message base.EnqueueMessage(new TcpIpMessage(stateObject.SBuilder.ToString())); // Start a new receive operation stateObject.SBuilder = new StringBuilder(); stateObject.Buffer.Clear(); stateObject.Buffer.Add(new ArraySegment(new byte[_bufferSize])); stateObject.TcpIpSocket.BeginReceive( stateObject.Buffer, SocketFlags.None, new AsyncCallback(ReceiveCallback), stateObject); } else { OnDisconnected(this, new Exception("Bytes returned are 0")); Disconnect(); } } } catch (Exception e) { // Something has gone wrong on a low level portion OnDisconnected(this, e); Disconnect(); } } 

在.NET中进行异步套接字读取的标准方法是在接收回调结束时重复调用BeginReceive 。 您似乎已接到已注释的必要调用。 我希望,只是解开这个电话并且一切都应该正常工作。 我没有对你的代码进行最详细的检查,所以我可能会遗漏一些东西,但这绝对是第一件要尝试的东西。 也许如果你详细说明你正在实现该方法的确切问题,我们可以帮助你多一点。

作为一个(轻微)的侧面点,如果您在.NET中进行TCP通信,我强烈建议您使用TcpClient类,如图所示。 这简化了大量低级套接字的工作,并且通常使TCP通信对程序员来说更加友好! 异步读取“循环”当然会大致相同。 此外,关于如何正确使用TcpClient类用于各种目的的MSDN和教程/代码片段(包括SO)上有大量文档(当您想要进行multithreading处理或重用TcpClient对象时,它会变得有点棘手) 。