在C#中在同一个套接字上发送+接收数据

我正在尝试使用套接字(System.Net.Socket,甚至尝试过TcpListener / Client / Etc。)来监听数据,而它正在等待或已经在发送数据。

我做了以下事情:

public byte[] bytesIn; public byte[] bytesOut; public Socket transmitter; public Socket receiver; public Comlink(String ipAddress, int portNum) { try { IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(ipAddress), 11000); transmitter = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); transmitter.Listen(10); receiver = transmitter.Accept(); receiver.Receive(bytesIn); try { transmitter.Connect(remoteEP); this.bytesOut = Encoding.ASCII.GetBytes(""); int bytesSent = transmitter.Send(this.bytesOut); this.connected = true; } } // (Omitted my exception handling.) } 

Receive()函数:

 this.bytesIn = new byte[1024]; Socket receiver = transmitter.Accept(); int bytesReceived = receiver.Receive(this.bytesIn); 

绑定它的代码:

 while(comlink.connected) { comlink.Receive(); handlePacket(comlink.bytesIn); } 

我只是不完全确定我是否使用正确的流程来接收数据,因为这一直是.NET的抱怨。 我需要处理数据。

像双向街道的东西:数据可以自由进入(程序不必返回到Receive()并等待数据),它会得到处理。 数据也可以从客户端自由移动到服务器。 我知道TCP套接字是双向的,但我需要改进这个类,以便我可以享受自由开放的道路带来的全部好处。

只显示您显示的代码至少有两个问题。 首先,您的套接字应该用于侦听或连接到远程套接字,但不能同时用于两者。 坦率地说,我很惊讶当代码在已经进入侦听模式后尝试调用Connect()时,.NET不会抛出exception。

其次,您只需要接受一次连接。 在每次调用Receive()之前接受是错误的,并且会导致代码仅从连接到它的每个套接字接收第一个缓冲区的数据。

通常,基于Socket的实现需要“服务器”和“客户端”。 请注意,一旦建立连接,角色就不需要保持如此牢固的建立。 但它们起初至关重要。

服务器将创建一个新的“监听”套接字。 使用此套接字,它将“接受”来自客户端的连接请求,该过程将创建实际用于通信的套接字。

我重申:服务器的原始套接字从不用于通过连接进行实际通信。 它只是用于创建连接的套接字。

客户端将创建一个套接字。 使用此套接字,它将尝试“连接”到服务器的套接字。 建立连接后,然后将相同的套接字用于实际通信。

如您所知,TCP连接是双向的。 因此,一旦建立连接,服务器和客户端就可以使用它们的单个套接字来连接发送和接收数据。 当然,请注意,在单线程代码中,您无法同时执行这两项操作。 因此,您的高级协议需要是一个呼叫和响应式协议,每个端口都能准确地知道何时需要发送或接收数据,并且它永远不需要同时执行这两个协议,或者您需要使用.NET为套接字提供的异步API之一,以便您可以同时处理发送和接收。

MSDN具有相当不错的Socket编程示例。 你应该从那里开始。

很久以前(无论如何在互联网年代:)),我写了一系列博客文章,试图帮助人们开始使用.NET Socket编程。 这是我找不到写作时间的少数事情之一; 如果它对您有帮助,您可以考虑检查它: http : //blogs.msmvps.com/duniho/2008/08/19/basic-network-programming-in-net/