我是一個.NET開發人員,是Socket編程的新手。多個線程到同一個TCP套接字
我寫了一個程序,該程序使用.NET套接字庫使用TCP套接字將一些數據發送到客戶端。
客戶端需要每40秒自定義一次Keep Alive消息才能保持連接處於活動狀態。
所以,我寫了一個與客戶端建立連接的主程序。在這個主程序中,我創建了一個線程並傳遞了之前創建的Socket類的實例。此線程負責將保持活動消息發送給客戶端,而主線程負責發送數據。
這一切都很好。但是,如果由於某種原因套接字連接超時,程序將永遠不會恢復?我把這兩個線程的邏輯都退出並建立了新的連接,但是它總會給出一個錯誤 - '與主機的連接被中止'或類似的東西。
我做錯了什麼?
我需要有兩個線程連接到同一個套接字。一個線程負責發送數據,另一個線程負責發送保持活動的消息。最好的辦法是什麼?
不,我不想使用相同的套接字。我掙脫離開環路和clntSock.close()...
下面是代碼:
我有mainThread調用handleClient。 handleClient創建另一個線程。
class DispatchLoop
{
ILogger logger;
TcpListener listener;
IProtocolFactory protoFactory;
public DispatchLoop(TcpListener listener, ILogger logger, IProtocolFactory protoFactory)
{
this.logger = logger;
this.listener = listener;
this.protoFactory = protoFactory;
}
public void mainThread()
{
// Run forever, accepting and handling each connection
for (; ;)
{
try
{
Socket clntSock = listener.AcceptSocket(); // Block waiting for connection
PoolDispatcher._stopper.Reset();
clntSock.ReceiveTimeout = 10000;
IProtocol protocol = protoFactory.createProtocol(clntSock, logger);
protocol.handleClient();
}
catch (SocketException se)
{
logger.writeEntry("(Run Dispatcher) Exception = " + se.Message);
}
}
}
}
public void handleClient()
{
entry.Add("Main Thread Entered : Client address and Port = " + clntSock.RemoteEndPoint + ", Thread Number = " + Thread.CurrentThread.GetHashCode());
//Kick Starting Keep Alive Thread
KeepAlive ka = new KeepAlive(clntSock, logger);
Thread thread = new Thread(new ThreadStart(ka.SendKeepAlive));
thread.Start();
try
{
int recvMsgSize; // Size of received message
byte[] rcvBuffer = new byte[BUFSIZE]; // Receive buffer
byte[] messageBuffer = new byte[1024];
XDocument _messageXDoc;
FlightInfoExtended _flightInfoExtended;
try
{
LogEntry(entry);
for (; ;)
{
try
{
//Read from the Queue
var _queue = new IBMQueue();
var message = _queue.ReceiveMessage();
if (message.Length > 0)
{
entry.Add("Sending the GOS Message to the client : " + message);
messageBuffer = Encoding.ASCII.GetBytes(message);
if (clntSock.Connected)
{
clntSock.Send(messageBuffer, 0, messageBuffer.Length, SocketFlags.None);
recvMsgSize = clntSock.Receive(rcvBuffer, 0, rcvBuffer.Length, SocketFlags.None);
SaveGOSMessage(_auditMessage);
}
else
{
PoolDispatcher._stopper.Set();
LogFailureStatus("No Socket Connection");
Thread.Sleep(30000);
break;
}
}
}
catch (SocketException se)
{
PoolDispatcher._stopper.Set();
LogFailureStatus(se.Message);
Thread.Sleep(30000);
break;
}
catch (Exception e)
{
}
LogEntry(entry);
}
}
catch (Exception se)
{
entry.Add(String.Format("{0}: {1}", se.Source, se.Message));
}
}
catch (Exception se)
{
entry.Add(String.Format("{0}: {1}", se.Source, se.Message));
}
clntSock.Close();
logger.writeEntry(entry);
}
public class KeepAlive
{
ArrayList entry;
private ILogger logger;
private Socket clntSock;
public const int BUFSIZE = 1024;
public KeepAlive(Socket clntSock, ILogger logger)
{
this.logger = logger;
this.clntSock = clntSock;
entry = new ArrayList();
}
void LogEntry(ArrayList _entry)
{
logger.writeEntry(_entry);
entry.Clear();
}
public void SendKeepAlive()
{
entry.Add("Keep Alive Thread Entered : Client address and Port = " + clntSock.RemoteEndPoint + ", Thread Number = " + Thread.CurrentThread.GetHashCode());
var message= "Some Keep Alive Message";
try
{
byte[] messageBuffer = new byte[1024];
LogEntry(entry);
for (; ;)
{
//Check if main thread died
if (PoolDispatcher._stopper.WaitOne(100, false))
{
break;
}
if (clntSock.Connected)
{
entry.Add("Sending the Keep Alive Message... " + message);
messageBuffer = Encoding.ASCII.GetBytes(message);
clntSock.Send(messageBuffer, 0, messageBuffer.Length, SocketFlags.None);
}
else
{
entry.Add("Socket Connection is not active. Keep Alive not sent");
break;
}
LogEntry(entry);
Thread.Sleep(30000);
}
}
catch (SocketException se)
{
entry.Add(String.Format("{0}: {1}", se.ErrorCode, se.Message));
}
catch (ObjectDisposedException ode)
{
entry.Add("Connection to the socket lost. Child Thread Aborted");
}
LogEntry(entry);
}
}
你試圖在終止後使用相同的套接字嗎?您將需要創建一個新的套接字,而不是嘗試重新使用舊套接字。 – drew010
您能否提供更多的代碼來展示如何建立新的連接?發佈所有相關的代碼可以讓別人更容易幫助你。 –
嗨...我已經添加了代碼...你們可以看看它,讓我知道我做錯了什麼?在handleClient中,如果出現錯誤,它將跳出循環,關閉套接字並將控制權返回給創建套接字的新實例的mainThread .... – InvisibleDev