みんなおはよう、
まず、やや一般的なタイトルでお詫び申し上げます。このメッセージの過程で、もう少し詳細な情報を思いつくことができれば、間違いなく変更します。
私は 3 つのプログラムを含むプロジェクトに取り組んでいます。目的は、接続されているすべてのクライアントに通知を送信できるようにすることです。このために、サーバー、クライアント、およびコンソール プログラムがあります。メッセージ自体は RTF ファイルになりますが、通知には送信部門 (文字列) と表示タイマー (TimeSpan) も必要です。
プロジェクトのほとんどが完了しました。ロジックはほぼ完成しており、マルチスレッド化されており、すべてのクラスの準備が整っており、ほとんどのテストが機能しています。
私が抱えている問題は、サーバーがコンソールから正しい順序でデータを受信していないように見えることです。それによってあらゆる種類の問題を引き起こします。
コンソールからサーバーへのプロセスは次のとおりです。
コンソールは、最初に通知に関連するすべての情報を選択します。
- ユーザー (リスト、LDAP から収集)
- 有効期限の日時 (DateTime)
- クローズまでの時間 (ロング、ティック数)
- 部門 (文字列)
- RTF ファイル
サーバーはすでにアクティブであり、コンソール接続用に別のスレッドがあります
- コンソールがサーバーに接続
- サーバーは、コンソール接続を処理するために別のスレッドを作成します
- コンソールは、ログオンしているユーザーのユーザー名をサーバーに送信します
- サーバーは、ユーザーが通知の作成を許可されているかどうかを確認します (今のところ、常に true を返します)
- コンソールは、すべての関連情報を次の順序で送信します。
- メッセージ ID (文字列)
- RecipientCount (サーバー側から適切にループするために使用されるユーザー数)
- 受信者 (リストの foreach ループ)
- 部門 (文字列)
- VisibleTime (長い)
- 有効期限 (日時)
- 最後にRTFファイル
System.Diagnostics.Trace を使用して、すべての情報が正しい順序で正しく送信されているかどうかを確認しました。これはすべてチェックアウトします。しかし問題は、およそ 75% の時間でサーバー側が RTF ファイルを受信しているように見えるということです。
コードは次のとおりです。
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);
}
}
誰かがこれに光を当てたり、私が何を変えるべきかを教えてくれたら.. または基本的に私を再び動かすことができるものなら何でも、私はとても感謝しています!