问题
I am working on a TCP Listener Service which waits for client to connect and receive files. The following code is used to initialize TCP Listener.
var listener= new TcpListener(IPAddress.Any, port);
listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
listener.Start();
Then waiting for client as
private void WaitForTcpClient(TcpListener listener){
while(!listener.Pending()){
Thread.Sleep(500);
}
listener.BeginAcceptTcpClient(BeginListeningInBackground, listener);
}
This is the method 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
}
}
It was working great when I tested on my local computer but after deployment, it started giving Socket Exception. The message by socket exception was as following. Even after catching exception, the same exception is constantly occurring. What is the cause of this exception and how can it be fixed?
回答1:
I'm not sure why it is problem, but i can see that you are using Sleep that will block the socket operations (I/O) and it could be the reason of your exception.
try this code, i tested before.
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);
}
}
}
I'm using your code to use to accept connections requests and read socket client in asynchronous ways, without use Sleeps.
- Start Socket Server and invoke an asynchronous method to accept connections (
BeginListeningInBackground). - Into
BeginListeningInBackgroundtheTCPClientsocket is created (EndAcceptTcpClient) and start to read, in asynchronous way, check the methodBeginToReadOnCLient(tcpClient);. - After accept the the connections the
TcpListenerwill be waiting for another connection:listener.BeginAcceptTcpClient(BeginListeningInBackground, listener);.
Into the method BeginToReadOnCLient the operation to read is asynchronous, usin the NetworkStream:
NetworkStream ns = client.GetStream();
bufferRx = new byte[10];
ns.BeginRead(bufferRx, 0, 10, ReadFromClientStream, ns);
ReadFromClientStream has a sample logic to read the data, you must implement the correct logic to read the information according with the communication protocol.
IMPORTANT: Read about how to use these asynchronous operations in NetworkStream to avoid exception at the moment of: Stop TcpListener, close a client Connection, send or read information and how many bytes have been received/read.
来源:https://stackoverflow.com/questions/52966108/tcplistener-throwing-socket-exception-on-listener-endaccepttcpclientasyncresult