为什么.NET / C#中的TCP网络(接收数据)在尝试接收时会抛出异常?

时间:2013-10-04 17:10:24

标签: c# .net sockets tcp

我一直在使用套接字在C#中发送数据并且它正在运行,使用以下代码:

string ipAddress = "x.y.z.a";   // replace with a real IP address
int port = 2809;
string data = "foo";

Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

if (!clientSocket.Connected)
    clientSocket.Connect(IPAddress.Parse(ipAddress), port);

clientSocket.Send(Encoding.UTF8.GetBytes(data));
clientSocket.Disconnect(true);
clientSocket.Close();
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

现在我希望它能够接收数据,但我无法让它工作,因为当我添加socket.Receive()时程序崩溃了。有人能指出我正确的方向吗?

1 个答案:

答案 0 :(得分:2)

正如Jon建议的那样, 你试图添加接收代码并不是很清楚。我的意思是,你的例子的最后一行有点令人困惑,因为你首先关闭套接字,然后创建一个新套接字。为什么?首先类似于“if(!clientSocket.Connected)”的东西;如果你创建一个新的套接字,应该没有必要检查它是否已连接。当然不是,你刚刚创造了它! : - )

无论如何,如果我只是在你的后面添加一些代码:

byte[] receiveBuffer = new byte[1024];
clientSocket.Receive(receiveBuffer);

...并相应地将ipAddressport更改为我网络上的已知良好服务,我收到一条SocketException,其中包含“请求不允许发送或接收数据,因为套接字未连接(使用sendto调用在数据报套接字上发送时)没有提供地址“

但是,如果我插入接收代码,以便发送/接收如下所示:

int bytesSent = clientSocket.Send(Encoding.UTF8.GetBytes(data));

var receiveBuffer = new byte[1024];
var sb = new StringBuilder();
int receivedBytes;
while ((receivedBytes = clientSocket.Receive(receiveBuffer)) != 0)
{
    // NOTE: this presumes that the data coming from the remote end is ASCII-
    // encoded, which might not be the case at all. Don't copy this approach
    // blindly without thinking
    string s = Encoding.ASCII.GetString(receiveBuffer, 0, receivedBytes);
    sb.Append(s);
}

var response = sb.ToString(); // at this point you should have all the data that
                              // has been received from the remote, so far.

clientSocket.Disconnect(true);
clientSocket.Close();

此代码适合我;它给了我对我的请求的回应(在我的情况下大约3 KiB)。

在更哲学/架构层面上,我绝对建议,如果你真的不需要需要到套接字级别(无论出于何种原因),而不是更喜欢使用其中一个框架的高级类。 WebClient是一种替代方案(适用于所有> 1.1版本的框架,例如,几乎所有今天都在使用的版本)。 HttpClient是另一个,如果您使用的是.NET 4.5(back-port available也有NuGet

当然,这盲目地假定你想要做的是执行HTTP请求(事实证明,这些日子很常见)。还有其他替代方法,如用于FTP的FtpWebRequest等等。

根据我的经验(作为程序员工作超过10年),实际上非常罕见的是必须深入到套接字级别,特别是最近给出了多少BCL(基类库,例如Microsoft提供的.NET标准程序集)或NuGet支持常见方案。这样的现有客户拥有巨大的巨大优势,其他人花了相当多的时间在上面,找出错误,怪癖等等,所以你可以开始关注你真正想要解决的问题,而不是修复bug实际上已经修复过很多次......

(当然,也有例外,但我觉得这绝对是一般的经验法则。)