TCP套接字超时

时间:2019-02-18 12:18:06

标签: c# tcp server client

我编写了C#程序,服务器仅将数据从服务器发送到客户端。 问题是两次发送数据之间的时间是可变的(最长5分钟) 有时会导致超时。

当我每3秒发送一次数据时,它们都没有超时。 但是,如果消息在5分钟后发送,则客户端可能无法接收它。

我做了客户端和服务器都具有的超时功能。超时后,每次重新连接:

public class TimerControl
{
    private System.Timers.Timer timeoutTimer = null;

    public void initTimeout(int timeMS, System.Timers.ElapsedEventHandler funct)
    {
        timeoutTimer = new System.Timers.Timer();
        timeoutTimer.Interval = timeMS; //MS
        timeoutTimer.Elapsed += funct;
        timeoutTimer.AutoReset = true;
        setTimeoutTimer(false);
    }

    public void setTimeoutTimer(bool state)
    {
        if (timeoutTimer != null)
        {
            timeoutTimer.Stop();
            timeoutTimer.Enabled = state;
            if (state) timeoutTimer.Start();
        }
    }
    public void resetTimeoutTimer()
    {
        if (timeoutTimer != null && timeoutTimer.Enabled)
        {
            timeoutTimer.Stop();
            timeoutTimer.Start();
        }
    }
}

没有解决问题的

我应该怎么做才能使其正常工作,并且在一段时间后不超时?

服务器:

public class TCPserver :TCPunit
{
    private int    TIMEOUT_MS  = 5000;

    Socket        serverListener = null;
    Queue<string> dataQueued     = null;

    bool isConnectedForced = false;



    public TCPserver()
    {
        dataQueued = new Queue<string>();

        initTimeout(TIMEOUT_MS, reconnect);
    }

    public void sendDataToClient(string message)
    {
        dataQueued.Enqueue(message + Environment.NewLine);
        if(isConnectedForced) startListening();
        if (dataQueued.Count > 0) setTimeoutTimer(true);
    }

    public bool connect(string adress)
    {
        this.thisUnitAdress = adress;
        isConnectedForced = true;
        loopedConnect();
        startListening();
        return true;
    }

    public bool disconnect()
    {
        isConnectedForced = false;
        loopedDisconnect();
        return true;
    }

    private bool loopedConnect()
    {

        try
        {
            IPAddress ipAddress = IPAddress.Parse(this.thisUnitAdress);
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);

            if (serverListener != null) loopedDisconnect();

            serverListener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            serverListener.Bind(localEndPoint);

            Console.WriteLine("SERVER connected to: " + this.thisUnitAdress + " port : " + port.ToString());
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("!!! SERVER connect");
            setTimeoutTimer(true);
            return false;
        }
    }

    private bool loopedDisconnect()
    {
        setTimeoutTimer(false);
        if (serverListener != null)
        {
            if (serverListener.Connected) serverListener.Shutdown(SocketShutdown.Both);
            serverListener.Close();
            Console.WriteLine("SERVER CLOSED!");
            serverListener = null;
        }
        return true;
    }


    private void reconnect(Object source, System.Timers.ElapsedEventArgs e)
    {
        if (isConnectedForced)
        {
            Console.WriteLine("SERVER RECONNECT!!!");
            loopedDisconnect();
            loopedConnect();
            if (dataQueued.Count > 0) setTimeoutTimer(true);
            else setTimeoutTimer(false);
        }
        else
        {
            setTimeoutTimer(false);
        }
    }

    private void startListening()
    {
        try
        {
            serverListener.Listen(100);
            Console.WriteLine("SERVER Waiting for a connection...");
            serverListener.BeginAccept(new AsyncCallback(AcceptCallback), serverListener);
            setTimeoutTimer(true);
        }
        catch (Exception ex)
        {
            Console.WriteLine("!!! SERVER sendingLOOP");
            setTimeoutTimer(true);
        }
    }

    private void AcceptCallback(IAsyncResult ar)
    {
        try
        {
            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);

            //HERE SEND
            while (dataQueued.Count > 0)
            {
                string data = dataQueued.Dequeue();
                byte[] byteData = Encoding.ASCII.GetBytes(data);
                handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
            }

            //handler.Shutdown(SocketShutdown.Both);
            //handler.Close();
            setTimeoutTimer(false);
        }
        catch (Exception ex)
        {
            Console.WriteLine("!!! SERVER AcceptCallback");
            setTimeoutTimer(true);
        }
    }


    private void SendCallback(IAsyncResult ar)
    {
        try
        {
            ((Socket)ar.AsyncState).EndSend(ar);
        }
        catch(Exception ex)
        {
            Console.WriteLine("!!! SERVER SendCallback");
            setTimeoutTimer(true);
        }
    }      

}

客户:

    public class TCPclient : TCPunit
{
    private int    TIMEOUT_MS     = 5000;

    Socket     client;
    IPEndPoint remoteEP;        

    bool isConnecting = false;
    bool isRecieving  = false;  // TELS IF PROGRAM SHOULD LOOK FOR SERVER ALL TIME

    Action<string> afterRecieveAction = null ; // To print to GUI


    public TCPclient()
    {
        initTimeout(TIMEOUT_MS, reconnect);
    }



    public void assignAfterRecieveAction(Action<string> action)
    {
        this.afterRecieveAction = action;
    }

    public bool connect(string adress)
    {
        thisUnitAdress = adress;
        loopedConnect();
        return true;
    }
    public bool disconnect()
    {
        isRecieving = false;
        isConnecting = false;
        loopedDisconnect();
        return true;
    }

    private bool loopedConnect()
    {                              

        IPAddress ipAddress = IPAddress.Parse(this.thisUnitAdress);
        remoteEP = new IPEndPoint(ipAddress, port);

        client = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

        setTimeoutTimer(true);
        isRecieving = true;
        StartClientListening();
        return true;
    }

    private bool loopedDisconnect()
    {
        if (client != null)
        {             
            if (client.Connected) client.Shutdown(SocketShutdown.Both);
            client.Close();

            Console.WriteLine("CLIENT CLOSED!");
            client = null;
        }
        return true;
    }
    private void reconnect(Object source, System.Timers.ElapsedEventArgs e)
    {
        if (isRecieving)
        {
            Console.WriteLine("CLIENT RECONNECT!!!");
            if (isConnecting) loopedDisconnect();
            isRecieving = true;
            loopedConnect();
        }
    }

    private void StartClientListening()
    {
        try
        {
            if (isRecieving)
            {
                client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback) , client);
                isConnecting = true;
                Console.WriteLine("CLIENT listens to: " + thisUnitAdress + " port : " + port.ToString());
            }
        }
        catch (System.Net.Sockets.SocketException ex)
        {
            Console.WriteLine("CLIENT StartClientListening");

        }
        catch (Exception ex)
        {
            Console.WriteLine("!!! CLIENT StartClientListening2");
            if (isRecieving) setTimeoutTimer(true);
        }
    }


    private void ConnectCallback(IAsyncResult ar)
    {
        try
        {
            client.EndConnect(ar);
            Console.WriteLine("CLIENT connected to {0}", client.RemoteEndPoint.ToString());
            StateObject state = new StateObject();
            state.workSocket = client;
            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state); ;
        }
        catch (Exception e)
        {              
            Console.WriteLine("!!! CLIENT ConnectCallback");
            if (isRecieving) setTimeoutTimer(true);
        }

    }


    private void ReceiveCallback(IAsyncResult ar)
    {
        try
        {
            StateObject state = (StateObject)ar.AsyncState;
            Socket client = state.workSocket;

            int bytesRead = client.EndReceive(ar);

            if (bytesRead > 0)
            {
                String response = Encoding.ASCII.GetString(state.buffer);
                if (afterRecieveAction != null) afterRecieveAction(response);
                resetTimeoutTimer();
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
            }                           
        }

        catch(System.Net.Sockets.SocketException ex)
        {
            Console.WriteLine("!!! CLIENT ReceiveCallback");
            if (isRecieving) setTimeoutTimer(true);
        }
        catch(Exception ex)
        {
            Console.WriteLine("!!! CLIENT ReceiveCallback2");
            if (isRecieving) setTimeoutTimer(true);
        }
    }

}

如何使异步服务器-客户端正常工作而不超时?

最好的问候, 克里斯

1 个答案:

答案 0 :(得分:0)

您应该使用socket_set_option对此参数进行设置