gpt4 book ai didi

c# - 如果没有及时收到网关服务器的确认,可能需要通过Socket重新发送数据

转载 作者:行者123 更新时间:2023-11-30 16:50:54 25 4
gpt4 key购买 nike

下面的代码用于将数据发送到网关服务器并作为响应接收确认。但有时没有收到确认,在这种情况下,我认为必须再次发送请求。下面的代码肯定不处理那部分。我想知道这个问题的任何可能的解决方案。

class TestSMS
{
public static string strIp = "10.00.105.00";
public static int Port = 1009;
//-----------------connect------------------//


public static Socket Connect(string host, int port)
{
Socket socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);

Console.WriteLine("Establishing Connection to {0}",
host);
socket.Connect(host, port);
clsError.LogError("TestSMS:Connect()", "Connection established");
return socket;
}



//---------------End connect----------------//

//-------------------send--------------------//



public static int SendReceiveTest(Socket server,string Message)
{
byte[] connectionString = Encoding.UTF8.GetBytes("CON^`!XML^`!ABCD#END#");
byte[] msg = Encoding.UTF8.GetBytes(Message);
byte[] bytes = new byte[1024];
string response = string.Empty;
int byteCount = 0;
int i = 0;
try
{
// Blocks until send returns.
i = server.Send(connectionString, connectionString.Length, SocketFlags.None);
clsError.LogError("TestSMS:SendReceiveTest()", "Connection string sent");

// Get reply from the server.
byteCount = server.Receive(bytes, server.Available,
SocketFlags.None);
if (byteCount > 0)
{
response = Encoding.UTF8.GetString(bytes);
if (response.IndexOf("CON!0") != 0)
{
i = server.Send(msg, msg.Length, SocketFlags.None);

clsError.LogError("TestSMS:SendReceiveTest()", "Message data sent");
byteCount = server.Receive(bytes, server.Available,
SocketFlags.None);
response = Encoding.UTF8.GetString(bytes);

if ((response.ToString().IndexOf("ACK!1") == 0) || (response.ToString().IndexOf("ACK!MSGSTATUS=TRUE") == 0))
{
clsError.LogError("TestSMS:SendReceiveTest()", "Message sent successfully: " + response);
}
//log

}
else
{
clsError.LogError("TestSMS:SendReceiveTest()", "Could not handshake with SMS Server");
}

}
else
{
clsError.LogError("TestSMS:SendReceiveTest()", "No Acknowledgement recieved");
}
}
catch (SocketException e)
{
clsError.LogError("TestSMS:SendReceiveTest()", e.Message.ToString());
return (e.ErrorCode);
}
return 0;
}



//-----------------End send------------------//

static void Main(string[] args)
{

try
{
string strXmlFormat = " MSG^`!<DEPT>IPL</DEPT><APPID>TLC</APPID><MOBILE>918879440021</MOBILE><DEPTMSGID>14092111115JH21075</DEPTMSGID><MESSAGE>This is a test message</MESSAGE><FROMDATETIME></FROMDATETIME><TODATETIME></TODATETIME><NODELIVERYTIMEFROM>2200</NODELIVERYTIMEFROM><NODELIVERYTIMETO>0700</NODELIVERYTIMETO><HTTPMODE>S</HTTPMODE><REMARKS></REMARKS><REMARKS1></REMARKS1><REMARKS2></REMARKS2><TRN_GENERATE_TIMESTAMP>2015-12-10 16:48:54 </TRN_GENERATE_TIMESTAMP>#END#";
clsError.LogError("Inside Main:Msg in XML format", strXmlFormat);
Socket Socket;
Socket = TestSMS.Connect(TestSMS.strIp, TestSMS.Port);

TestSMS.SendReceiveTest(Socket, strXmlFormat);


}
catch (Exception ex)
{
clsError.LogError("Inside Main:Main()", ex.Message.ToString());
throw ex;

}

}



}

最佳答案

问题:

您的主要问题在 server.Receive陈述(有两个)

 byteCount = server.Receive(bytes, server.Available, SocketFlags.None); //only read when byte is available

一旦有来自套接字的回复,此语句本身将被传递,但不一定在接收到所有数据之后。

这是我通过在我的 PC 中模拟该过程捕获的内容:

enter image description here
  • 在上图中,程序一直运行到server.Receive行,但等待响应。因此它不会转到 if (byteCount > 0)线。 Form右边是我的模拟网关服务器。它表明它收到了消息。

  • enter image description here
  • 在上图中,我向客户端发送了回复“DummyReply”。程序运行到行 if (byteCount > 0)但是,看看那个(!),byteCount是零!这是核心的错误。我为 SendReceiveTest 做了一个循环看看接下来发生了什么...

  • enter image description here
  • 右侧Form显示客户端又发送了一条测试消息并且服务器没有给它任何回复但它直接转到 if (byteCount > 0)行并查看 byteCount值(value)。它是 10(这是“DummyReply”消息长度!),也就是 上一页 我从服务器发送的回复!

  • 因此,很明显 server.Receive为您的系统带来问题。

    深吸一口气……

    解决方案:

    我个人可能很想用 ASync 来解决这个问题。而不是 Sync ,但允许您的程序无法通过 ASync 解决的可能性出于某种原因,以下是我将根据您的代码执行的操作:
    //-------------------send--------------------//
    public static int SendReceiveTest(Socket server, string Message) {
    byte[] connectionString = Encoding.UTF8.GetBytes("CON^`!XML^`!ABCD#END#");
    byte[] msg = Encoding.UTF8.GetBytes(Message);
    byte[] bytes = new byte[1024];
    string response = string.Empty;
    int byteCount = 0;
    int i = 0;
    try {
    i = server.Send(connectionString, connectionString.Length, SocketFlags.None); // Blocks until send returns.
    clsError.LogError("TestSMS:SendReceiveTest()", "Connection string sent");

    // Get reply from the server.
    int retryCount = 0, retryLimit = 5; //declare these two new variables
    while (retryCount < retryLimit) { //repeats the waiting as long as it is within the retry limit
    if (server.Available > 0) //check for the available byte first, please change 0 with number of bytes which you expected
    byteCount = server.Receive(bytes, server.Available, SocketFlags.None); //only read when byte is available
    retryCount++;
    //Log the retry count here if your wish: clsError.LogError("Retry Count: " + retryCount.ToString(), "Retry attempt to get response");
    if (byteCount > 0 && retryCount < retryLimit) //if there is byte received at this point or condition violated, break
    break;
    System.Threading.Thread.Sleep(1000); //no byte received re-check in another second;
    }

    if (byteCount <= 0) { // no byte received
    clsError.LogError("TestSMS:SendReceiveTest()", "No Acknowledgement recieved");
    return -1; //change this with your own error code
    } //passing this point means you receive something
    response = Encoding.UTF8.GetString(bytes);
    if (response.IndexOf("CON!0") == 0) {
    clsError.LogError("TestSMS:SendReceiveTest()", "Could not handshake with SMS Server");
    return -2; //change this with your own error code
    } //passing this points means response.IndexOf("CON!0") != 0

    retryCount = 0; //reset retry count, change retryLimit as per necessary if needed be
    byteCount = 0; //reset byte count
    i = server.Send(msg, msg.Length, SocketFlags.None); //"Message data sent"

    while(retryCount < retryLimit) { //similar concept with above
    if (server.Available > 0) //check for the available byte first, please change 0 with number of bytes which you expected
    byteCount = server.Receive(bytes, server.Available, SocketFlags.None); //only read when byte is available
    //Log the retry count here if your wish: clsError.LogError("Retry Count: " + retryCount.ToString(), "Retry attempt to get message");
    retryCount++;
    if (byteCount > 0 && retryCount < retryLimit) //if there is byte received at this point or condition violated, break
    break;
    System.Threading.Thread.Sleep(1000); //no byte received re-check in another second;
    }

    if (byteCount <= 0) {
    //Log here accordingly. i.e.: clsError.LogError("TestSMS:GetMessage()", "No message received");
    return -3; //change this with your error code
    } //passing this point means you receive the message

    response = Encoding.UTF8.GetString(bytes);
    if ((response.ToString().IndexOf("ACK!1") == 0) || (response.ToString().IndexOf("ACK!MSGSTATUS=TRUE") == 0)) {
    clsError.LogError("TestSMS:SendReceiveTest()", "Message sent successfully: " + response);
    }
    //log

    } catch (SocketException e) {
    clsError.LogError("TestSMS:SendReceiveTest()", e.Message.ToString());
    //return (e.ErrorCode); //not sure if this is a good idea, I rather change this.
    //If you really need e.ErrorCode, it would have been better to create `out` parameter in the method
    return -4; //Socket exception
    }
    return 0; // at this point, ideally there is no error at all
    }
    //-----------------End send------------------//
  • 首先,我将把嵌套的 if-else 分解成
    if { /*simple case*/ return errorCode; } //continue

    这样,在错误发生时一一处理会容易得多。 (更多将在后面展示)
  • 我将引入一个错误代码来返回不同的结果,然后,如果需要,我将创建 switch关于如何处理不同错误代码的处理程序。 IE。
    if (errorCode != 0){ //if there is error code.
    switch(errorCode){
    case -1: //no ack
    //do something, such as repeating the process X times
    break;
    case -2: //fail to handshake
    //do something
    break;
    ... and so on
    }
    }

    为此,我也不会通过函数本身返回默认套接字错误代码(在 exception 上),因为它会干扰我定义的错误代码。但是如果需要,这个套接字错误代码可以返回 out方法中的关键字。然后,在 case -4: 下处理此套接字错误信息(使用我的例子)。

    注:如有重新发送 由于未收到确认或任何其他各种错误原因而需要,应在此处完成。
    case -1:
    if (repeatNumber < repeatLimit) {
    SendReceiveTest(server, message); //repeats
    repeatNumber++; //reset this number when successful
    } else {
    //do something, it fails!
    }
    break;
  • 第三,关于问题的核心,我会用server.Available作为在处理之前首先检查是否有任何可用数据的一种方式
    if (server.Available > 0) //check for the available byte first, please change 0 with number of bytes which you expected
    byteCount = server.Receive(bytes, server.Available, SocketFlags.None); //only read when byte is available

    这样,它就不会运行 server.Receive命令接收之前的字节数size你期望的最低限度。

    注意:仍然存在数据包 split 的可能性(一些数据先收到,一些数据在后收到)。在这种情况下,最好在处理数据之前进行更多检查。我向您展示的案例仅限于给出关于如何处理主要问题的主要想法。有一些在线资源可用于解决您很容易找到的其他问题(例如数据包拆分)。
  • 最后,来到这个技巧的主要部分,我会将“聆听”(或接收)部分包装在 while 中。在 retryCount 的帮助下,用于重试目的的循环, retryLimit , 和 System.Threading.Thread.Sleep .
    int retryCount = 0, retryLimit = 5;
    while (retryCount < retryLimit) { //repeats the waiting as long as it is within the retry limit
    if (server.Available > 0) //check for the available byte first, please change 0 with number of bytes which you expected
    byteCount = server.Receive(bytes, server.Available, SocketFlags.None); //only read when byte is available
    retryCount++;
    //Log the retry count here if your wish: clsError.LogError("Retry Count: " + retryCount.ToString(), "Retry attempt to get response");
    if (byteCount > 0 && retryCount < retryLimit) //if there is byte received at this point or condition violated, break
    break;
    System.Threading.Thread.Sleep(1000); //no byte received re-check in another second;
    }

    if (byteCount <= 0) { // no byte received
    clsError.LogError("TestSMS:SendReceiveTest()", "No Acknowledgement recieved");
    return -1; //change this with your own error code
    } //passing this point means you receive something

  • 祝一切顺利!

    关于c# - 如果没有及时收到网关服务器的确认,可能需要通过Socket重新发送数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34332435/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com