我正在编写一个c#tcp套接字服务器,它将从c++套接字应用程序接收数据。现在,除了我的c#接收线程中的循环中断逻辑之外,一切都很好。我在下面展示了一个代码片段来更好地解释。
//creating socket object
private Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//accepting connections
TcpListener tcpListener = new TcpListener(ipAdd, iPort);
tcpListener.Start();
this.socket = tcpListener.AcceptSocket();
tcpListener.Stop();
//code for
//public byte[] ReceiveMessage(ref int intError)
while (this.socket.Available > 0)
{
try
{
intBytesReceived = this.socket.Receive(byteReceivedBuffer, byteReceivedBuffer.Length, SocketFlags.None);
Thread.Sleep(100);
}
catch (SocketException ex)
{
string str = ex.Message;
intError = -1;
}
}
以下是连续接收数据的线程函数
//Thread to continuous poll data from client
//Now this has been done as I need to receive multiple messages from client after server ack received at client side.
//Thread quit logic based on manual stop button press
//I want to have one more logic by which thread will exit if the connection closed by client socket. i.e. a call of 'CloseSocket()' function from c++ application.
if (TCPServerListener.serverStatus == TCPServerListener.ServerStatus.Stopped)
{
tcpCommunication.Disconnect();
break;
}
while(true)
{
int sockError = 0;
byte[] byteData = tcpCommunication.ReceiveMessage(ref sockError);
if (byteData.Length > 0)
{
ParseBuffer(byteData, ref tcpCommunication);
}
}
为了更好的图片,我在我的通讯协议下面写下了文字。
- 客户端启动连接。发送数据集
- 服务器接收、处理、发送ack
- 客户端处于暂停模式,直到它从服务器接收到ack,但没有关闭套接字
- 这一次,服务器将不会接收到任何消息,但接收线程应该是活动的,因为我正在为每个客户端创建一个线程
- 一旦客户端收到ack,它将继续发送下一个数据
- 服务器接收线程现在将获取数据并进行相应处理
- 一旦客户端关闭其套接字,服务器接收器线程也应该关闭
我可以完成我的工作,但服务器接收器线程没有关闭。这是我的问题。任何建议都会很有帮助。
根据我的经验,当您使用TCP服务器/客户端套接字关系时,TCP服务器套接字端将位于一个由标志控制的线程中,以继续侦听,直到被告知停止(您的评论中提到了停止按钮)。
客户端运行,直到所有数据都完成,或者控制服务器端的相同标志被触发。
当客户端连接时,我会将AcceptSocket存储到一个列表中。当我这样做的时候,我有一个自定义类,它接受AcceptSocket,这个自定义类有计数器,比如向这个客户端发送/接收了多少消息或字节。
// This should be a threaded method if you're using a button to stop
private void StartTcpListener()
{
List<ClientClass> clientClassList = new List<ClientClass>();
TcpListener tcpListener = new TcpListener(ipAdd, iPort);
tcpListener.Start();
while (keepListening)
{
Socket socket = tcpListener.AcceptSocket();
// Create a client object and store it in a list
ClientClass clientClass = new ClientClass(socket);
clientClassList.Add(clientClass);
// This method would start a thread to read data from the accept socket while it was connected.
clientClass.Start();
}
foreach (ClientClass client in clientClassList)
{
// This method would stop the thread that reads data from the accept socket and close the accept socket
client.Stop();
}
tcpListener.Stop();
}
对于客户端,当从客户端接受套接字读取时,这将由线程控制,线程被中止,或者客户端关闭其末端,导致读取返回-1表示读取的字节数。
// Threaded method
private void Receive()
{
// Don't know how much of a buffer you need
byte[] dataIn = byte[1000];
while (acceptSocket.Connected)
{
// Exception handling so you either end the thread or keep processing data
try
{
int bytesRead = acceptSocket.Read(dataIn);
if (bytesRead != -1)
{
// Process your data
}
else
{
// -1 Bytes read should indicate the client shutdown on their end
break;
}
}
catch(SocketException se)
{
// You could exit this loop depending on the SocketException
}
catch(ThreadAbortException tae)
{
// Exit the loop
}
catch (Exception e)
{
// Handle exception, but keep reading for data
}
}
// You have to check in case the socket was disposed or was never successfully created
if (acceptSocket != null)
{
acceptSocket.Close();
}
}
// This is the stop method if you press your stop button
private void Stop()
{
// Aborts your read thread and the socket should be closed in the read thread. The read thread should have a ThreadState.Stopped if the while loop was gracefully ended and the socket has already been closed
if (readThread != null && readThread.ThreadState != ThreadState.Stopped)
{
readThread.Abort();
}
}
我认为这是我以前所做的基本工作。我相信现在有"更干净"的方法可以做到这一点。这是几年前我用来实现TCP客户端/服务器套接字对象的时候。
希望这能帮助。。。