C# 不能';t建立与TcpListener的连接
在过去的两周里,我一直试图解决一个问题,但显然没有成功。 我有一个使用TcpListener类的服务器和一个使用TcpClient类的客户端 我的测试是在我的内部家庭网络(1级路由器)中使用2台计算机。 尝试连接时,客户端计算机出现“连接请求超时”异常 我已经尝试过的:C# 不能';t建立与TcpListener的连接,c#,sockets,tcplistener,C#,Sockets,Tcplistener,在过去的两周里,我一直试图解决一个问题,但显然没有成功。 我有一个使用TcpListener类的服务器和一个使用TcpClient类的客户端 我的测试是在我的内部家庭网络(1级路由器)中使用2台计算机。 尝试连接时,客户端计算机出现“连接请求超时”异常 我已经尝试过的: 在同一台计算机上运行客户机和服务器是有效的 正在0.0.0.0端口6666上侦听(请与netstat联系以确保服务器正在侦听) 禁用客户端和服务器防火墙 试图用telnet连接我的远程应用程序(拒绝“客户端代码错误”的可能性)
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace Utils
{
public class ClientConnection
{
public ClientConnection(IPHostEntry hostName, TcpClient client)
{
HostName = hostName;
Client = client;
}
public IPHostEntry HostName { get; set; }
public TcpClient Client { get; set; }
}
public class SocketServer : IDisposable
{
private const int DefaultRecieveSize = 1024;
protected const int ReceiveTimeoutBeforeQuiting = 5000;
private readonly Encoding _defaultEncoding = Encoding.ASCII;
private readonly TcpListener _socket;
protected Dictionary<IPAddress, ClientConnection> Clients;
private static object _locker;
private readonly AutoResetEvent _listeningStopEvent;
private readonly Thread _listeningThread;
private readonly AutoResetEvent _acceptNewClientEvent;
public delegate void ClientsListChangedEvent();
public event ClientsListChangedEvent ClientsChangedEvent;
private Timer _refreshClientsTimer;
private static int _updateClientListInterval;
#region Ctors
protected SocketServer(int port)
{
_socket = new TcpListener(IPAddress.Parse("0.0.0.0"),port);
Clients = new Dictionary<IPAddress, ClientConnection>();
_updateClientListInterval = Convert.ToInt32(ConfigurationManager.AppSettings["UpdateClientListInterval"]);
_listeningThread = new Thread(AcceptNewConnections);
_listeningStopEvent = new AutoResetEvent(false);
_acceptNewClientEvent = new AutoResetEvent(false);
_locker = new object();
_socket.Start();
}
#endregion
#region Send methods
protected void SendString(IPAddress client, string data)
{
// implementation here
}
#endregion
#region Receieve methods
protected MemoryStream GetInputDataAsMemoryStream(IPAddress client)
{
// implementation here
}
protected string GetInputDataAsMemoryString(IPAddress client)
{
// implementation here
}
protected string GetInputDataAsMemoryString(IPAddress client, int timeout)
{
// implementation here
}
#endregion
#region Listening methons
public void StopListening()
{
_listeningStopEvent.Set();
// todo : check if works
_refreshClientsTimer.Dispose();
}
public bool StartListening()
{
if (_listeningThread.ThreadState == ThreadState.Unstarted)
{
_listeningThread.Start();
// start refreshing clients list too. update clients list every 10 seconds
_refreshClientsTimer = new Timer(UpdateList, null, 0, _updateClientListInterval * 1000);
return true;
}
return false;
}
private void AddClientCallback(IAsyncResult ar)
{
// get all needed data before entering lock
if (_socket != null)
{
TcpClient client;
try
{
client = _socket.EndAcceptTcpClient(ar);
}
catch (ObjectDisposedException)
{
// probebly server has been closed. exit
return;
}
var clientEndPoint = client.Client.RemoteEndPoint;
var ip = SocketFunctions.ExtractIpFromEndPoint(clientEndPoint);
IPHostEntry hostName;
try
{
hostName = SocketFunctions.ExtractHostnameFromEndPoint(clientEndPoint);
}
catch(SocketException)
{
// error while parsing from ip to host name. Put default
hostName = new IPHostEntry();
}
// check if given ip already connected
if (!Clients.ContainsKey(ip))
{
lock (_locker)
{
Clients.Add(ip, new ClientConnection(hostName, client));
}
// notify that a new clients has been added
ClientsChangedEvent.Invoke();
}
}
// a new client has accepted
_acceptNewClientEvent.Set();
}
private void AcceptNewConnections(object obj)
{
var shouldStop = false;
while (!shouldStop)
{
_socket.BeginAcceptTcpClient(AddClientCallback, null);
AutoResetEvent[] events = { _listeningStopEvent, _acceptNewClientEvent };
var result = WaitHandle.WaitAny(events);
if (result == 0)
{
shouldStop = true;
}
}
}
#endregion
public List<KeyValuePair<string, string>> GetConnectedClients()
{
var connectedClients = new List<KeyValuePair<string, string>>();
lock (_locker)
{
foreach (var client in Clients)
{
// get only connected clients. Don`t remove - next Timer round will do it anyway and I don`t want to lock _clients
if (client.Value.Client.Connected)
{
connectedClients.Add(new KeyValuePair<string, string>(client.Key.ToString(), client.Value.HostName.HostName));
}
}
}
return connectedClients;
}
private static void CheckConnectionStatus(TcpClient client)
{
if (client.Client.Poll(0, SelectMode.SelectRead))
{
var checkConn = new byte[1];
checkConn[0] = 0;
try
{
if (client.Client.Receive(checkConn, SocketFlags.Peek) == 0)
{
throw new IOException();
}
}
catch (SocketException)
{
// for me, both exceptions mean that there was a conncetion error. Throw IOException for this case too
throw new IOException();
}
}
}
public void UpdateList(object obj)
{
// iterate each client and check its state. Remove if not connected
var tempClients = new Dictionary<IPAddress, ClientConnection>(Clients);
var changedOccurred = false;
lock (_locker)
{
foreach (var client in Clients)
{
try
{
CheckConnectionStatus(client.Value.Client);
}
catch (IOException)
{
// client is not connected anymore
tempClients.Remove(client.Key);
changedOccurred = true;
}
}
}
if (changedOccurred)
{
lock (_locker)
{
Clients = tempClients;
}
// notify that a new clients has been added
ClientsChangedEvent.Invoke();
}
}
#region IDisposble
public void Dispose()
{
if (_socket != null)
{
StopListening();
_socket.Stop();
}
}
#endregion
}
使用系统;
使用System.Collections.Generic;
使用系统配置;
使用System.IO;
Net系统;
使用System.Net.Sockets;
使用系统文本;
使用系统线程;
命名空间Utils
{
公共类客户端连接
{
公共客户端连接(IPHostEntry主机名、TcpClient客户端)
{
主机名=主机名;
客户=客户;
}
公共IPHostEntry主机名{get;set;}
公共TcpClient客户端{get;set;}
}
公共类SocketServer:IDisposable
{
private const int defaultReceiveSize=1024;
退出前受保护常数int ReceiveTimeOut=5000;
私有只读编码_defaultEncoding=Encoding.ASCII;
专用只读TcpListener\u套接字;
受保护的词典客户端;
私有静态对象_locker;
私有只读AutoResetEvent _ListingStopEvent;
私有只读线程_listingthread;
私有只读自动存储事件_acceptNewClientEvent;
公共委托void ClientsListChangedEvent();
公共事件客户的变更客户的变更;
私人定时器(刷新客户端定时器);;
私有静态int_updateClientListInterval;
#区域系数
受保护的SocketServer(int端口)
{
_套接字=新的TcpListener(IPAddress.Parse(“0.0.0.0”),端口);
Clients=newdictionary();
_updateClientListInterval=Convert.ToInt32(ConfigurationManager.AppSettings[“updateClientListInterval]”);
_ListingThread=新线程(AcceptNewConnections);
_ListingStopEvent=新的自动还原事件(false);
_acceptNewClientEvent=新的自动恢复事件(false);
_locker=新对象();
_socket.Start();
}
#端区
#区域发送方法
受保护的void SendString(IPAddress客户端,字符串数据)
{
//在这里实现
}
#端区
#区域接收方法
受保护内存流GetInputDataAsMemoryStream(IPAddress客户端)
{
//在这里实现
}
受保护字符串GetInputDataAsMemoryString(IPAddress客户端)
{
//在这里实现
}
受保护的字符串GetInputDataAsMemoryString(IPAddress客户端,int超时)
{
//在这里实现
}
#端区
#区域监听法
公营部门
{
_ListingStopEvent.Set();
//todo:检查是否有效
_refreshClientsTimer.Dispose();
}
公共广播
{
如果(_listingThread.ThreadState==ThreadState.Unstarted)
{
_listingThread.Start();
//也开始刷新客户端列表。每10秒更新一次客户端列表
_refreshClientsTimer=新计时器(UpdateList,null,0,_updateClientListInterval*1000);
返回true;
}
返回false;
}
私有void AddClientCallback(IAsyncResult ar)
{
//在进入锁之前获取所有需要的数据
if(_socket!=null)
{
TCP客户机;
尝试
{
客户端=_socket.endAcceptCpcClient(ar);
}
捕获(ObjectDisposedException)
{
//可能服务器已关闭。退出
返回;
}
var clientEndPoint=client.client.RemoteEndPoint;
var ip=SocketFunctions.ExtractIpFromEndPoint(clientEndPoint);
iphonestry主机名;
尝试
{
hostName=SocketFunctions.ExtractHostnameFromEndPoint(clientEndPoint);
}
捕获(SocketException)
{
//从ip解析到主机名时出错。将默认设置为
hostName=新的IPHostEntry();
}
//检查给定的ip是否已连接
如果(!Clients.ContainsKey(ip))
{
锁(储物柜)
{
添加(ip,新客户端连接(主机名,客户端));
}
//通知已添加新客户端
ClientsChangedEvent.Invoke();
}
}
//一个新客户已经接受了
_acceptNewClientEvent.Set();
}
私有void AcceptNewConnections(对象obj)
{
var shouldStop=false;
而(!应该停止)
{
_BeginAcceptTcpClient(AddClientCallback,null);
AutoResteEvent[]事件={U ListingStopEvent,{U acceptNewClientEvent};
var result=WaitHandle.WaitAny(事件);
如果(结果==0)
{
shouldStop=true;
}
}
}
#端区
公共列表GetConnectedClient()
{
var connectedClients=新列表();
锁(储物柜)
{
foreach(客户机中的var客户机)
{
//仅获取已连接的客户端。不要删除-下一个计时器循环wil