程序当前有效:您输入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
}
}
我试图修改它,所以如果服务器/接收方在客户端/发送方向其发送消息时暂时脱机,发送方将自动等待十秒钟,然后尝试重新连接并重新发送消息。 / p>
现在我可以通过手动等待,然后重新点击&#34; connect&#34;然后&#34;发送&#34;但是我希望发件人自己处理它。
表单代码:
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();
}
}
第一次在这里发帖,我希望我做对了。欢迎任何建议。
答案 0 :(得分:1)
基本答案是将消息和目标放入队列中。 并尝试发送,如果成功将其从队列中删除。
鉴于您可能有多个目的地,每个目的地都需要一个队列。 Dictionary<IP,List<Message>>
作为原始选项。
此时有很多潜在的优化,以及发送到群组等扩展。
答案 1 :(得分:0)
首先,在返回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);
}
}