c#,尝试发送消息,如果离线自动休眠,重新连接,重新发送

标签 c# winforms sockets chat send

该程序当前工作:您输入 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();                                 
    }
}

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

最佳答案

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

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

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

关于c#,尝试发送消息,如果离线自动休眠,重新连接,重新发送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21505694/

相关文章:

c# - 应用程序在另一个线程中不会故意崩溃

C# 等效于 MessageBoxA(HWND_DESKTOP, msg, "Alarm", MB_OK | MB_ICONWARNING | MB_SYSTEMMODAL | MB_SETFOREGROUND);

javascript - JS 文件得到一个 net::ERR_ABORTED 404 (Not Found)

ios - 如果 iPhone 应用程序正在运行(心跳),则处理服务器知道

c++ - 将ZeroMQ与Boost::ASIO一起使用

c# - 音频转换 C#

c# - Procdump -e 在非致命异常上创建转储

c# - 在 asp.net 中单击按钮时的 url 重写问题

c# - 如何将C# Winform Project连接到局域网中的XAMPP MySQL服务器?

C# LinearGradientBrush 位图垂直重复