在过去的两周里,我一直试图解决问题,但显然没有成功。 我有一个使用TcpListener类的服务器和一个使用TcpClient类的客户端。
我的测试是在我的内部家庭网络(1级路由器)中使用2台计算机。 试图连接,客户端计算机得到"连接请求超时"异常。
我已经尝试过的事情:
仍然我的服务器似乎没有任何连接。客户端计算机是Windows XP,服务器计算机是Windows 7。
请帮助,我真的坚持这个。
编辑 - 服务器代码 - >
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
}
}