【问题标题】:c#, attempt to send message, if offline automatically sleep, reconnect, resendc#,尝试发送消息,如果离线自动休眠,重新连接,重新发送
【发布时间】:2014-02-25 15:50:47
【问题描述】:

程序当前工作:输入IP地址,点击连接,输入消息,点击发送,服务器接收并显示消息。

客户代码:

 public class Client
 {
    private const int DataSize = 65635;
    private byte[] data = new byte[DataSize];
    public Socket _socket;                      //the main socket
    public string strMsg;                       //sender's message string


    {
        get                                   
        {
            IPHostEntry ipHostInfo = Dns.GetHostEntry("localhost");   
            IPAddress ipAddress = ipHostInfo.AddressList[1];        
            return ipAddress.ToString();                 
        }
    }

    public EndPoint _epHost;   

    public bool Connect(string address)  
    {
        bool result = false; 
        if (string.IsNullOrEmpty(address)) return false;
        try
        {
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
                 ProtocolType.Tcp);
            IPAddress ipAddress = IPAddress.Parse(address);  
            IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 8040);
            _epHost = (EndPoint)ipEndPoint;
            _socket.Connect(_epHost);
            result = true; 
        }
        catch (SocketException ex)
        {
            throw new Exception(ex.Message);
        }
        return result; 
    }

    // CITATION: Send() is a modified form of code by Jan Slama on his website
    // Link: http://www.csharp-examples.net/socket-send-receive/
    // License: "simple, straightforward examples suitable for copy and paste"

    public void Send(Data mailToBeSent, int offset, int timeout)
    {
        int startTickCount = Environment.TickCount;
        int sent = 0;  // how many bytes is already sent  

        data = mailToBeSent.ToByte();

            do
            {
                if (Environment.TickCount > startTickCount + timeout)
                {
                    data = null;
                    throw new Exception("Timeout.");
                }
                try
                {
                    sent += _socket.Send(data, offset + sent, 
                       data.Length - sent, SocketFlags.None);
                }
                catch (SocketException ex)
                {
                    if (ex.SocketErrorCode == SocketError.WouldBlock ||
                        ex.SocketErrorCode == SocketError.IOPending ||
                        ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
                        // socket buffer is probably full, wait and try again
                        Thread.Sleep(30);
                    else
                        throw ex;  // any serious error occurs
                }
            }
            while (sent < data.Length);
    }

    public void Close()
    {
        if (_socket != null)
        {                
            _socket.Shutdown(SocketShutdown.Both);
            _socket.Close();
        }
    }
}

public enum Command         //Commands for sender/receiver
{
    Message,                //Send a text message to the receiver
    Close,                  //Close
    Null,                   //No command
}
}

我正在尝试修改它,如果客户端/发送方向其发送消息时服务器/接收方暂时离线,发送方将自动等待十秒钟,然后尝试重新连接并重新发送消息。

现在我可以通过手动等待,然后重新单击“连接”然后“发送”来做到这一点,但我希望发件人自行处理。

表格代码:

  public partial class Form1 : Form
{

    private Client _client;

    public Form1()          
    {
        InitializeComponent();                              
        _client = new Client();                                    
        Text = string.Format("Address: {0}", _client.IpAddress);    
        btnDisconnect.Enabled = false;                              
        tbMsg.Enabled = false;                                     
        btnSend.Enabled = false;                                   
    }

    private void btnConnect_Click(object sender, EventArgs e)   
    {
        if (_client.Connect(tbAddress.Text))    
        { 
            btnDisconnect.Enabled = true;       
            tbMsg.Enabled = true;               
            btnSend.Enabled = true;             
            tsLabel.Text = "Online";            
        }
    } 


    private void btnSend_Click(object sender, EventArgs e) 
    {
       try
       {
          Data mailToBeSent = new Data();            
          mailToBeSent.cmdCommand = Command.Message;
          mailToBeSent.ipAddress = _client.IpAddress; 
          mailToBeSent.strMessage = tbMsg.Text;      
          _client.Send(mailToBeSent, 0, 1000);       
          tbMsg.Text = string.Empty;                         
        }
        catch (Exception)
        {
          MessageBox.Show("Unable to deliver mail to receiver.", "Client", 
            MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }


    private void btnDisconnect_Click(object sender, EventArgs e) 
    {
        Data mailToBeSent = new Data();                    
        mailToBeSent.cmdCommand = Command.Close;           
        mailToBeSent.ipAddress = _client.IpAddress;        
        mailToBeSent.strMessage = string.Empty;            
        _client.Send(mailToBeSent, 0, 1000);               
        _client.Close();                                 
    }
}

第一次在这里发帖,希望我做对了。欢迎任何建议。

【问题讨论】:

  • 是否允许用户再次单击按钮并发送另一条消息,而您仍在重试上一条消息?如果是,应该优先发送什么消息?

标签: c# winforms sockets chat send


【解决方案1】:

首先,在返回bool的新方法中提取消息代码的发送:

private bool SendMessage()
{
   try
   {
      Data mailToBeSent = new Data();            
      mailToBeSent.cmdCommand = Command.Message;
      mailToBeSent.ipAddress = _client.IpAddress; 
      mailToBeSent.strMessage = tbMsg.Text;      
      _client.Send(mailToBeSent, 0, 1000);       
      tbMsg.Text = string.Empty;                         
    }
    catch (Exception)
    {
       return false;
    }

    return true;
}

然后在您的按钮单击事件中检查它是否成功,如果不成功,请等待并重试:

private void btnSend_Click(object sender, EventArgs e) 
{
    int noOfRetries = 0;

    while(!SendMessage() && noOfRetries < 3) // Or whatever no of retries you want
    {
        noOfRetries++;
        Thread.Sleep(10000);
    }
}

【讨论】:

  • 这将阻止 UI 长达 30 秒,在最坏的情况下。
  • 感谢您提供的信息;没有意识到我试图用一种方法做太多事情。虽然在其他程序中 30 秒的阻塞可能是个问题,但在这种情况下应该可以正常工作。
  • 好的,如果您发现任何给定的回复是满意的答案,您应该将其标记为您的问题的答案,灰色复选标记。这将帮助其他人看到问题已得到解答。
【解决方案2】:

基本答案是将消息和目标放入队列中。 并尝试发送,如果成功则将其从队列中删除。

鉴于您可能有多个目的地,您需要为每个目的地排队。 Dictionary&lt;IP,List&lt;Message&gt;&gt; 作为原始选项。

当时有很多潜在的优化,以及发送到群组等扩展。

【讨论】:

    猜你喜欢
    • 2021-04-27
    • 2015-11-08
    • 1970-01-01
    • 2012-08-04
    • 2019-07-06
    • 1970-01-01
    • 2012-01-30
    • 1970-01-01
    • 2018-09-20
    相关资源
    最近更新 更多