【问题标题】:Send TCP response after SQL Service Broker completes its operationsSQL Service Broker 完成操作后发送 TCP 响应
【发布时间】:2015-01-21 16:10:09
【问题描述】:

我的应用程序当前侦听 TCP 端口并将入站数据解析为 xml。我遇到的问题是应用程序需要发回一个响应,其中包含由服务代理应用程序创建的一组不同的 xml。我对网络应用程序编程非常陌生,并且对入站/出站的处理方式没有深入的了解。在这一点上,一切正常,但我似乎能生成的唯一响应是“来自客户端的最后一条消息 - ” + 发送内容的回声。这是我的 TCP 服务器的代码...

public static void ReceivePortMessages()
{
    IPAddress ip = Dns.GetHostEntry("sctest.com").AddressList[0];
    TcpListener serverSocket = new TcpListener(ip, 8080);
    int requestCount = 0;
    TcpClient clientSocket = default(TcpClient);
    serverSocket.Start();
    Debug.Print(" >> Server Started");
    clientSocket = serverSocket.AcceptTcpClient();
    Debug.Print(" >> Accept connection from client");
    requestCount = 0;

    while (true)
    {
        try
        {
            requestCount = requestCount + 1;
            NetworkStream networkStream = clientSocket.GetStream();
            byte[] bytesFrom = new byte[10025];
            networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
            Stopwatch sw = new Stopwatch();
            sw.Start();
            string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
            dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("\0"));
            Debug.Print(" >> Data from client - " + dataFromClient);
            string serverResponse = "Last Message from client" + dataFromClient;
            Byte[] sendBytes = Encoding.ASCII.GetBytes(serverResponse);
            networkStream.Write(sendBytes, 0, sendBytes.Length);
            networkStream.Flush();
            Debug.Print(" >> " + serverResponse);

            try
            {
                XmlDocument xm = new XmlDocument();
                xm.LoadXml(string.Format("<root>{0}</root>", dataFromClient));
                XmlElement root = xm.DocumentElement;
                string rootName = root.FirstChild.Name;
                RouteInboundXML(rootName, dataFromClient, sw);
            }
            catch (Exception ex)
            {
                Debug.Print("Data provided does not match any predefined XML schemas; it will be ignored.");
            }
        }
        catch (ArgumentOutOfRangeException ex)
        {
            Debug.Print("Remote client disconnected.");
            clientSocket.Close();
            serverSocket.Stop();
            ReceivePortMessages();
            return;
        }
        catch (Exception ex)
        {
            Debug.Print(ex.ToString());
            clientSocket.Close();
            serverSocket.Stop();
            ReceivePortMessages();
            return;
        }
        Debug.Print(" >> exit");
    }
}

我真正需要做的是发送响应的代码部分,在服务代理拍摄 xml 数据、修改它并返回一个新的 xml 字符串之后发送响应。

private void PingReplyDependency()
{
    try
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        if (!isPermitted())
        {
            return;
        }
        using (SqlConnection con = new SqlConnection(dbUSApp))
        using (SqlCommand cmd = con.CreateCommand())
        {
            cmd.CommandText = PING_AWAIT;
            cmd.CommandType = CommandType.Text;
            cmd.Notification = null;
            con.Open();
            using (SqlDataReader dr = cmd.ExecuteReader())
            {
                if (dr.HasRows)
                {
                    while (dr.Read())
                    {
                        PingReply ping = new PingReply();
                        ping.REPLY_CODE = dr["REPLY_CODE"].ToString();
                        WriteXMLFile<PingReply>(ping, string.Format(@"XML\PingSend{0}.xml", ping.TRAN_ID));

                        string rowPointer = dr["RowPointer"].ToString();
                        using (SqlConnection conInsert = new SqlConnection(dbP3USDApp))
                        using (SqlCommand cmdInsert = NonQueryCommand("[SP_DO_Xml]", conInsert,
                            new SqlParameter("@RowPointer", rowPointer)))
                        {
                            conInsert.Open();
                            cmdInsert.ExecuteNonQuery();
                        }
                    }
                }
            }
        }
    }
    catch (Exception ex)
    {
        ErrorLog.Write("Notification System", ex.ToString(), "SystemAvailabilityReply", Environment.UserName, "Failed Ping.");
    }
}

如果需要更多信息或说明,请告诉我。我试图只发布我认为必不可少的内容,但从外部角度来看,我可能错过了重要的部分。提前致谢。

【问题讨论】:

  • 接收严重中断。您需要处理Read 一次只能返回一个字节的事实。要么使用循环来排出传入的内容,要么直接将 NetworkStream 传递给 XML 库,以便它可以提取 XML。
  • @usr 你能详细说明一下吗。我能找到的这个过程的几乎每个例子都是这样的。你能给我看一些代码,至少可以开始朝那个方向发展吗?

标签: c# sockets tcp response tcplistener


【解决方案1】:

TCP 是基于流的。这意味着 TCP 中没有应用程序消息的表示法。 TCP 所理解的是,它正在发送一个字节流,其中没有消息之间的分隔。

对您而言,这意味着可以分割一条消息,以便您必须使用多个socket.Receive() 才能获得完整的消息,或者您可以在一个socket.Receive() 中获得多个完整的消息。

因此,您必须找出某种方法来了解消息的开始或结束位置。通常使用长度标头或消息分隔符。

如果您不想自己处理所有事情,可以使用我的 Apache 许可网络库:http://griffinframework.net/doc/networking

【讨论】:

  • 'substring.indexof("\0")' 在每个 semt 字符串的末尾找到我的消息的结尾。你指的是这个吗?这些消息也是预定义的模板。
  • 您假设networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize); 将包含完整的消息。这是不正确的。您还应该检查来自Read 的返回值,因为0 表示远程端点已断开连接。
猜你喜欢
  • 1970-01-01
  • 2015-12-22
  • 1970-01-01
  • 1970-01-01
  • 2020-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多