套接字连接中的C#BeginSend和BeginReceive问题

时间:2016-06-01 09:21:09

标签: c# winforms visual-studio sockets server

我在C#应用程序中使用BeginSend和BeginReceive。它是一个客户端侦听器,只接收来自服务器的数据。我正在使用BeginReceive来获取数据。

但我发现只接受接收不足以使连接保持活跃和稳定。因此,我决定让我的应用程序始终ping服务器以使用BeginSend保持连接活动。

以下是我的代码:

private void timer1_Tick(object sender, EventArgs e)
{
    DataProcess();
}

public Socket _serverSocket = null;
private byte[] _recieveBuffer = new byte[128];
byte[] AllBytes;
void DataProcess()
{
    //TimeSpan ts;
    try
    {
        //Thread.Sleep(100);
        if (_serverSocket == null || sockState == MySocketState.Disconnected)
        {
            Console.WriteLine("Trying to connect...");
            SetupServer();
        }
        else
        {
            AllBytes = ASCIIEncoding.ASCII.GetBytes(COM_DeviceIsOnline);
            _serverSocket.BeginSend(AllBytes, 0, AllBytes.Length, SocketFlags.None, new AsyncCallback(SendCallback), null);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

private void SetupServer()
{
    try
    {
        _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        _serverSocket.Connect(_sIP, Int32.Parse(_sPort));
    }
    catch (SocketException ex)
    {
        Console.WriteLine(ex.Message);
    }

    if (_serverSocket.Connected)
    {
        sockState = MySocketState.Connected;
        browser.ExecuteScriptAsync("svrConnect();");
        Console.WriteLine("Server connected...");
        _serverSocket.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
    }
}

void SendCallback(IAsyncResult ar)
{
    try
    {
        int bytesSent = _serverSocket.EndSend(ar);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

private void ReceiveCallback(IAsyncResult AR)
{
    try
    {
        if (_serverSocket == null)
            _serverSocket = (Socket)AR.AsyncState;

        //Check how much bytes are recieved and call EndRecieve to finalize handshake
        int recieved = _serverSocket.EndReceive(AR);

        if (recieved <= 0)
        {
            CloseSocket();
            return;
        }

        //Copy the recieved data into new buffer , to avoid null bytes
        byte[] recData = new byte[recieved];
        Buffer.BlockCopy(_recieveBuffer, 0, recData, 0, recieved);
        string strData = ASCIIEncoding.ASCII.GetString(recData);
        Console.WriteLine(strData);

        //Process data here the way you want , all your bytes will be stored in recData

        int nSOHPos = -1;
        int nSTXPos = -1;
        int nETXPos = -1;
        int nEOTPos = -1;

        nSOHPos = Array.IndexOf(recData, SOH);
        nSTXPos = Array.IndexOf(recData, STX);
        nETXPos = Array.IndexOf(recData, ETX);
        nEOTPos = Array.IndexOf(recData, EOT);

        if ((nSOHPos == -1) || (nSTXPos == -1) || (nETXPos == -1) || (nEOTPos == -1))
        {
            CloseSocket();
            return;
        }

        if (nSOHPos > nSTXPos ||
                nSTXPos > nETXPos ||
                nETXPos > nEOTPos)
        {
            CloseSocket();
            return;
        }

        if ((nETXPos - nSTXPos) < 6)
        {
            CloseSocket();
            return;
        }

        string _sCommand = ASCIIEncoding.ASCII.GetString(recData, nSTXPos + 6, 2);

        if ((_sCommand == "CN") || (_sCommand == "CL") || (_sCommand == "CR"))
        {
            nDept = int.Parse(ASCIIEncoding.ASCII.GetString(recData, nSTXPos + 12, 2));
            if (nDept != dept_id) return;
            nCntr = int.Parse(ASCIIEncoding.ASCII.GetString(recData, nSTXPos + 14, 2));
            nServ = int.Parse(ASCIIEncoding.ASCII.GetString(recData, nSTXPos + 16, 2));
            sQnum = ASCIIEncoding.ASCII.GetString(recData, nSTXPos + 8, 4);
            string[] sSplit = strData.Split('^');
            string sCusName = sSplit[1];
            //if (_sCommand == "CR") sCusName = " ";
            Console.WriteLine("Dept ID = " + nDept);
            Console.WriteLine("Cntr ID = " + nCntr);
            Console.WriteLine("Serv ID = " + nServ);
            Console.WriteLine("Queue No = " + sQnum);
            Console.WriteLine("Cus Name = " + sCusName);
            var script = string.Format("nextCall(\'{0}\', {1}, {2});", sQnum, nCntr, nServ);
            browser.ExecuteScriptAsync(script);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
        CloseSocket();
    }
    finally
    {
        try
        {
            //Start receiving again
            if (_serverSocket != null)
                _serverSocket.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
            //theDevSock.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, ReceiveCallback, theDevSock);
        }
        catch (Exception ex2)
        { }
    }
}

public void CloseSocket()
{
    try
    {
        if (_serverSocket != null)
        {
            if (_serverSocket.Connected)
                _serverSocket.Shutdown(SocketShutdown.Both);
            _serverSocket.Close();
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
    _serverSocket = null;
    sockState = MySocketState.Disconnected;
    browser.ExecuteScriptAsync("svrDisconnect();");
}

我的应用程序开始连接到服务器。连接到服务器后,它将开始ping服务器。但我发现每次使用BeginSend ping服务器后,错误“线程0x1ff0已经退出代码259(0x103)。”并且将断开与服务器的连接,我的应用程序将重新尝试再次连接服务器。然后在成功连接并再次ping服务器后,它再次断开连接。

我可以知道我的编码是否写得正确?我可以像这样使用BeginSend ping服务器吗?

1 个答案:

答案 0 :(得分:0)

我添加了以下代码来发送ping:

        private void timer2_Tick(object sender, EventArgs e)
    {
        pingServer();
    }

    void pingServer()
    {
        if (_serverSocket != null || sockState == MySocketState.Connected)
        {
            Console.WriteLine("Ping Server");
            AllBytes = ASCIIEncoding.ASCII.GetBytes(COM_DeviceIsOnline);
            //_serverSocket.BeginSend(AllBytes, 0, AllBytes.Length, SocketFlags.None, new AsyncCallback(SendCallback), null);
            SendTCPData(0x01, 1, 1, 1, "AA", "");
        }
    }

    public bool SendTCPData(byte bySequenceNo, int nSlaveID, int nDeviceID,
                            int nStatus, String strCommand, String strData)
    {
        return SendTCPData(ACK, bySequenceNo, nSlaveID, nDeviceID, nStatus, strCommand, strData);
    }

    public bool SendTCPData(byte byTypeCode, byte bySequenceNo,
                            int nSlaveID, int nDeviceID,
                            int nStatus, String strCommand,
                            String strData)
    {
        return SendTCPData(byTypeCode, bySequenceNo, nSlaveID, nDeviceID,
                            nStatus, strCommand, strData, 0);
    }

    public bool SendTCPData(byte byTypeCode, byte bySequenceNo,
                            int nSlaveID, int nDeviceID,
                            int nStatus, String strCommand, String strData, int nProtocolType)
    {
        byte[] AllBytes;
        String strTemp;
        try
        {
            strTemp = nSlaveID.ToString("0#") +
              nDeviceID.ToString("0#") +
              nStatus.ToString() +
              strCommand + strData;

            if (nProtocolType == 0)
            {

                AllBytes = new byte[strTemp.Length + 7];
                AllBytes[0] = SOH;
                AllBytes[1] = byTypeCode;
                AllBytes[2] = (byte)((int)bySequenceNo | 0x80);
                AllBytes[3] = STX;
                ASCIIEncoding.ASCII.GetBytes(strTemp).CopyTo(AllBytes, 4);
                AllBytes[AllBytes.Length - 3] = ETX;
                AllBytes[AllBytes.Length - 2] = 128;
                AllBytes[AllBytes.Length - 1] = EOT;
            }
            else
            {
                AllBytes = new byte[strTemp.Length + 6];
                AllBytes[0] = SOH;
                AllBytes[1] = STX;
                ASCIIEncoding.ASCII.GetBytes(strTemp).CopyTo(AllBytes, 2);
                AllBytes[AllBytes.Length - 4] = ETX;
                AllBytes[AllBytes.Length - 3] = ETX;
                AllBytes[AllBytes.Length - 2] = 128;
                AllBytes[AllBytes.Length - 1] = EOT;
            }
            //Debug.WriteLine("Sending data to " + _sIPAddr + " -> " + ASCIIEncoding.ASCII.GetString(AllBytes));
            return SendByte(AllBytes, AllBytes.Length);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
        return false;

    }

    public bool SendByte(byte[] pByteData, int nLength)
    {
        try
        {
            if  (_serverSocket == null) return false;
            if (!_serverSocket.Connected) return false;
            Console.WriteLine("SendByte = " + ASCIIEncoding.ASCII.GetString(pByteData, 0, nLength));
            //Debug.WriteLine("SendByte Length= " + nLength.ToString() );
            _serverSocket.BeginSend(pByteData, 0, nLength, SocketFlags.None,
                SendCallback, _serverSocket);
            //dtLastActivity = DateTime.Now;
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            CloseSocket();

        }
        return false;
    }

我使用30秒计时器发送ping,只要它与服务器有连接,它就会发送ping。现在,它已经可以检测到未插入的电缆。

我可以知道你们对这个答案的看法是什么吗?

相关问题