我正在研究TCP侦听器服务,该服务等待客户端连接和接收文件。 以下代码用于初始化TCP侦听器。
var listener= new TcpListener(IPAddress.Any, port);
listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
listener.Start();
然后等待客户
private void WaitForTcpClient(TcpListener listener){
while(!listener.Pending()){
Thread.Sleep(500);
}
listener.BeginAcceptTcpClient(BeginListeningInBackground, listener);
}
这是BeginListeningInBackground方法。
private async void BeginListeningInBackground(IAsyncResult asyncResult){
var listener = asyncResult.AsyncState as TcpListener;
var tcpClient = listener.EndAcceptTcpClient(asyncResult);
Task.Run(() =>
{
WaitForTcpClient(listener);
});
using (NetworkStream netStream = tcpClient.GetStream()){
//working with netStream here
}
}
当我在本地计算机上进行测试时,它工作得很好,但是在部署之后,它开始提供Socket Exception。套接字异常消息如下。 即使在捕获异常之后,相同的异常仍在不断发生。造成此异常的原因是什么?如何解决?
答案 0 :(得分:1)
我不确定为什么会出现问题,但是我可以看到您正在使用Sleep
来阻止套接字操作(I / O),这可能是导致异常的原因。
尝试此代码,我之前已经测试过。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Dummy
{
public partial class Form1 : Form
{
TcpListener listener;
byte[] bufferRx;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
int port = 9982;
listener = new TcpListener(IPAddress.Any, port);
listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
listener.Start();
//Begin to start the first connection
System.Console.WriteLine("Waitting for client");
listener.BeginAcceptTcpClient(BeginListeningInBackground, listener);
}
private void BeginListeningInBackground(IAsyncResult asyncResult)
{
System.Console.WriteLine("new for client request.");
var listener = asyncResult.AsyncState as TcpListener;
var tcpClient = listener.EndAcceptTcpClient(asyncResult);
BeginToReadOnCLient(tcpClient);
System.Console.WriteLine("Waitting for next client");
listener.BeginAcceptTcpClient(BeginListeningInBackground, listener);
}
private void BeginToReadOnCLient(TcpClient client)
{
System.Console.WriteLine("Initi Rx on Client");
NetworkStream ns = client.GetStream();
bufferRx = new byte[10];
ns.BeginRead(bufferRx, 0, 10, ReadFromClientStream, ns);// (BeginListeningInBackground, listener);
}
private void ReadFromClientStream(IAsyncResult asyncResult)
{
NetworkStream ns = (NetworkStream)asyncResult.AsyncState;
System.Console.WriteLine("Read Data from client. DATA:[" + System.Text.Encoding.Default.GetString(bufferRx) + "]");
bufferRx = new byte[10];
ns.BeginRead(bufferRx, 0, 10, ReadFromClientStream, ns);
}
}
}
我正在使用您的代码以异步方式接受连接请求和读取套接字客户端,而无需使用Sleeps
。
BeginListeningInBackground
)。BeginListeningInBackground
套接字(TCPClient
到EndAcceptTcpClient
套接字中,并开始以异步方式读取方法BeginToReadOnCLient(tcpClient);
。TcpListener
将等待另一个连接:listener.BeginAcceptTcpClient(BeginListeningInBackground, listener);
。 在BeginToReadOnCLient
中,要读取的操作是异步进入方法NetworkStream
:
NetworkStream ns = client.GetStream();
bufferRx = new byte[10];
ns.BeginRead(bufferRx, 0, 10, ReadFromClientStream, ns);
ReadFromClientStream
具有读取数据的示例逻辑,您必须实施正确的逻辑以根据通信协议读取信息。
重要:在以下情况下,了解如何在NetworkStream
中使用这些异步操作来避免出现异常:停止TcpListener,关闭客户端连接,发送或读取信息以及多少字节已被接收/读取。