TCP套接字上的长连接

时间:2016-06-21 08:37:10

标签: sockets tcp

你能帮忙吗?我正在与根据制造商需要长连接选项的设备集成。你知道如何做到这一点吗?

这是我到目前为止的代码,它在大多数情况下有效:

public AsynchronousSocketListener(IPEndPoint endPoint, ILog log)
{
    _EndPoint = endPoint;
    _log = log;
    Console.WriteLine(String.Format("Started: {0}:{1}", endPoint.Address, endPoint.Port));
}

public void StartListening()
{
    // Data buffer for incoming data.
    byte[] bytes = new Byte[1024];

    // Create a TCP/IP socket.
    Socket socket = new Socket(AddressFamily.InterNetwork,
    SocketType.Stream, ProtocolType.Tcp);
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

    // Bind the socket to the local endpoint and listen for incoming connections.
    try
    {

        socket.Bind(_EndPoint);
        socket.Listen(100000);
        Console.WriteLine("Listen");

        while (true)
        {
            // Set the event to nonsignaled state.
            allDone.Reset();

            // Start an asynchronous socket to listen for connections.
            socket.BeginAccept(
                    new AsyncCallback(AcceptCallback),
                    socket);

            // Wait until a connection is made before continuing.
            allDone.WaitOne();
        }

    }
    catch (Exception ex)
    {
        Console.WriteLine(String.Format("Error:{0}", ex.Message));
    }
}


public void AcceptCallback(IAsyncResult ar)
{
    // Signal the main thread to continue.
    allDone.Set();

    // Get the socket that handles the client request.
    Socket listener = (Socket)ar.AsyncState;
    Socket handler = listener.EndAccept(ar);

    // Create the state object.
    StateObject state = new StateObject();
    state.workSocket = handler;
    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
        new AsyncCallback(ReadCallback), state);
}

public void ReadCallback(IAsyncResult ar)
{
    String content = String.Empty;

    // Retrieve the state object and the handler socket
    // from the asynchronous state object.
    StateObject state = (StateObject)ar.AsyncState;
    Socket handler = state.workSocket;

    // Read data from the client socket. 
    int bytesRead = handler.EndReceive(ar);

    if (bytesRead > 0)
    {
        // There  might be more data, so store the data received so far.
        state.sb.Append(Encoding.ASCII.GetString(
            state.buffer, 0, bytesRead));

        // Check for end-of-file tag. If it is not there, read 
        // more data.
        content = state.sb.ToString();
        Console.WriteLine(String.Format("RECEIVED: {0}", content));
        if (content.IndexOf("\u0001") > -1)
        {
            string imei = string.Empty;
            foreach (string response in ResponseHandler.GetRequestResponse(content, out imei))
            {
                Send(handler, response, imei);
                Console.WriteLine(String.Format("RESPONSE: {0}", response));
            }
        }
        else
        {
            // Not all data received. Get more.
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
            new AsyncCallback(ReadCallback), state);
        }
    }
}

private void Send(Socket handler, String data, string imei)
{
    // Convert the string data to byte data using ASCII encoding.
    byte[] byteData = Encoding.ASCII.GetBytes(data);
    //Terminator
    byte[] terminator = new byte[3] { 0x01, 0x01, 0x01 };
    //Create new array with added 3 spaces for terminator
    byte[] terminalResponse = new byte[byteData.Length + 3];
    //Copy command byte array to new array
    byteData.CopyTo(terminalResponse, 0);
    //Copy terminator byte array to new array
    terminator.CopyTo(terminalResponse, terminalResponse.Length - 3);

    // Begin sending the data to the remote device.
    handler.BeginSend(terminalResponse, 0, terminalResponse.Length, 0,
        new AsyncCallback(SendCallback), handler);
}

private static void SendCallback(IAsyncResult ar)
{
    try
    {
        // Retrieve the socket from the state object.
        Socket handler = (Socket)ar.AsyncState;

        // Complete sending the data to the remote device.
        int bytesSent = handler.EndSend(ar);

        //handler.Shutdown(SocketShutdown.Both);
        //handler.Close();

    }
    catch (Exception e)
    {
        Console.WriteLine(e.ToString());
    }
}

提前致谢

2 个答案:

答案 0 :(得分:0)

感谢答案人员,我没有对此作出回应,但发现SocketOptionName.KeepAlive似乎解决了这个问题:

// Create a TCP/IP socket.
Socket socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

确保套接字最后没有关闭。

答案 1 :(得分:-1)

这可能对某人有所帮助,或者如果你能看到如何改善这一点,请告诉我。但这是我目前使用的版本:

public async Task StartListening()
{
    // Data buffer for incoming data.
    byte[] bytes = new Byte[1024];

    // Create a TCP/IP socket.
    Socket socket = new Socket(AddressFamily.InterNetwork,
    SocketType.Stream, ProtocolType.Tcp);
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

    // Bind the socket to the local endpoint and listen for incoming connections.
    try
    {
        socket.Bind(_EndPoint);
        socket.Listen(100000);
        Console.WriteLine(String.Format("Socket connected to {0}", _EndPoint.Address));

        while (true)
        {
            // Program is suspended while waiting for an incoming connection.  
            Socket handler = socket.Accept();
            data = null;

            // An incoming connection needs to be processed.  
            while (true)
            {
                bytes = new byte[1024];
                int bytesRec = handler.Receive(bytes);
                data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
                if (data.IndexOf("\u0001") > -1)
                {
                    break;
                }
            }

           Console.WriteLine(String.Format("RECEIVED: {0}", data));

            // Echo the data back to the client.  
            byte[] msg = Encoding.ASCII.GetBytes(data);

            handler.Send(msg);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(String.Format("Error:{0}", ex.Message));
    }
}