大家早上好,
首先为有点笼统的标题道歉。如果在这个消息的过程中我能想出一些更详细的东西,我一定会改变它。
我正在开发一个包含 3 个程序的项目。目的是能够向所有连接的客户端发送通知。为此,有一个服务器、客户端和控制台程序。消息本身将是一个 RTF 文件,但通知还需要一个发送部门(字符串)和一个显示计时器(TimeSpan)。
大部分项目已经完成。逻辑大部分是完整的,它是多线程的,所有的类都准备好了,并且大多数测试都可以工作。
我遇到的问题是服务器似乎没有以正确的顺序从控制台接收数据。从而引发各种问题。
从控制台到服务器的过程如下:
控制台首先选择通知的所有相关信息:
- 用户(列表,从 LDAP 收集)
- 到期日期和时间 (DateTime)
- 允许关闭前的时间(长,刻度数)
- 部门(字符串)
- RTF 文件
服务器已经处于活动状态,并且有一个单独的线程用于控制台连接
- 控制台连接到服务器
- 服务器创建一个单独的线程来处理控制台连接
- 控制台将登录用户的用户名发送到服务器
- 服务器检查是否允许用户创建通知(现在它总是返回 true)
- 控制台按以下顺序发送所有相关信息:
- 消息 ID(字符串)
- RecipientCount(用户数,用于从服务器端适当循环)
- 收件人(列表的 foreach 循环)
- 部门(字符串)
- 可见时间(长)
- 到期(日期时间)
- 最后是 RTF 文件
我使用 System.Diagnostics.Trace 来检查所有信息是否以正确的顺序正确发送。这一切都检查出来了。但问题是,大约 75% 的时间服务器端似乎在接收 RTF 文件时应该接收到 visibleTime。
代码如下:
private void SendMessage()
{
SendToServer(Environment.UserName);
if (bool.Parse(ReadFromServer()))
{
// User is allowed, continue
string messageID = DateTime.Now.ToUniversalTime().Ticks.ToString();
SendToServer(messageID); // MessageID
string recipientCount = lvRecipients.Items.Count.ToString();
SendToServer(lvRecipients.Items.Count.ToString()); // Amount of recipients
foreach (string item in lvRecipients.Items) // Loop to send each recipient
{
SendToServer(item);
}
string department = TB_Department.Text;
SendToServer(department); // Send department string
string visibleTime = TimeSpan.FromSeconds(SLIDER_VisibleTime.Value).Ticks.ToString();
SendToServer(visibleTime); // Send message visibility time
string expiration = DateTime.Now.ToUniversalTime().AddMinutes(2).ToString();
SendToServer(expiration); //TODO add UI control for this
SendRTFToServer(); // Send RTF file
MessageBox.Show(
"Your designated MessageID is: " + messageID + Environment.NewLine +
"Message upload is succesful.",
"Complete",
MessageBoxButton.OK);
}
else
{
// User is not allowed. Report to user. Disconnect (will be managed by the finally block)
MessageBox.Show(
"You are not allowed to upload messages to the server.",
"Access denied",
MessageBoxButton.OK,
MessageBoxImage.Stop);
return;
}
}
private void SendToServer(string toSend)
{
StreamWriter writer = new StreamWriter(server.GetStream());
writer.WriteLine(toSend);
writer.Flush();
}
private void SendRTFToServer()
{
StreamReader rtfFile = new StreamReader(File.Open(RTFLocation, FileMode.Open, FileAccess.Read));
StreamWriter sw = new StreamWriter(server.GetStream());
sw.Write(rtfFile.ReadToEnd());
sw.Flush();
server.GetStream().Flush();
}
private string ReadFromServer()
{
server.GetStream().Flush();
StreamReader reader = new StreamReader(server.GetStream());
return reader.ReadLine();
}
从服务器:
private void Connect()
{
string username = ReadFromConsole();
if (IsUserAllowed(username)) // Receive username
SendToConsole(bool.TrueString); // Send confirmation
else
{
SendToConsole(bool.FalseString); // Send denial
console.Close();
return;
}
string messageID = ReadFromConsole(); // Receive MessageID
string recipientCount = ReadFromConsole();
int numOfRecipients = int.Parse(recipientCount); // Receive and parse number of recipients
List<string> recipients = new List<string>();
for (int i = 0; i < numOfRecipients; i++)
{
string recipient = ReadFromConsole();
recipients.Add(recipient); // Receive recipient, add to list (required for Message)
}
string department = ReadFromConsole(); // Receive department string
string visibleTime = ReadFromConsole();
string expiration = ReadFromConsole();
StoreRTF(messageID); // Receive and store RTF file
console.Close(); // Connection is done, close
Message message = new Message(messageID, department, recipients, visibleTime, expiration);
}
private void SendToConsole(string toSend)
{
// Open client stream, and write information to it.
StreamWriter writer = new StreamWriter(console.GetStream());
writer.WriteLine(toSend);
writer.Flush();
}
private string ReadFromConsole()
{
// Read information from client stream
StreamReader reader = new StreamReader(console.GetStream());
return reader.ReadLine();
}
private void StoreRTF(string messageID)
{
// Check/create folder for Message storage
string messageFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\BMNotify\";
if (!Directory.Exists(messageFolder))
Directory.CreateDirectory(messageFolder);
// Create file to store message in
Stream rtfFile = File.Create(messageFolder + messageID + ".rtf");
// Store information from stream, and close resources
console.GetStream().CopyTo(rtfFile);
rtfFile.Close();
rtfFile.Dispose();
}
和消息类:
public class Message
{
internal string messageID;
internal string department;
internal List<string> recipients;
internal TimeSpan visibleAtLeast;
internal DateTime messageExpiration;
private static List<Message> allMessages; // Will hold te collection of Message's
public Message(string _messageID, string _department, List<string> _recipients, string visibleTime, string expiration)
{
messageID = _messageID;
recipients = _recipients;
department = _department;
visibleAtLeast = TimeSpan.FromTicks(long.Parse(visibleTime));
messageExpiration = DateTime.Parse(expiration);
if (allMessages == null)
allMessages = new List<Message>(); // Initialize if required
allMessages.Add(this);
}
internal Stream GetRTF()
{
return File.Open
(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\BMNotify\" + messageID + ".rtf",
FileMode.Open,
FileAccess.Read,
FileShare.Read);
}
static public List<Message> AllMessages()
{
if (allMessages == null)
allMessages = new List<Message>(); // Initialize if required
return allMessages;
}
static public void RemoveMessage(Message message)
{
allMessages.Remove(message);
}
}
如果有人能对此有所了解,或者告诉我应该改变什么......或者基本上任何能让我重新开始的事情,我将非常感激!