Я пытаюсь проработать основы простого tcp клиент / сервера, чтобы я мог внедрить систему уведомлений, которая будет работать практически где угодно и позволять приложениям, подобным «демонам», взаимодействовать.Одним из клиентов может быть монитор, который просматривает сообщения и показывает состояние всех сбросов и координирует их, например, приостанавливая один или несколько, просматривая, сколько файлов было обработано, каково состояние базы данных и т. Д.Для начала мне нужен очень простой сервер, который ждет сообщений от клиентов и передает их другим клиентам.Вот моя настоящая попытка на сервере (на примере http://csharp.net -informations.com / communications / csharp-chat-server.htm ).
using System;
using System.Threading;
using System.Net.Sockets;
using System.Text;
using System.Collections;
namespace erc.bre
{
class NotificationServer
{
public static Hashtable clientsList = new Hashtable();
static void Main(string[] args)
{
System.Net.IPAddress addr = System.Net.IPAddress.Parse("127.0.0.1");
TcpListener serverSocket = new TcpListener(addr, 1025);
TcpClient clientSocket = default(TcpClient);
int counter = 0;
serverSocket.Start();
Console.WriteLine("Chat Server Started ....");
counter = 0;
while ((true))
{
counter += 1;
clientSocket = serverSocket.AcceptTcpClient();
byte[] bytesFrom = new byte[10025];
clientSocket.ReceiveBufferSize = bytesFrom.Length; // added
string dataFromClient = null;
NetworkStream networkStream = clientSocket.GetStream();
// Console.WriteLine("Bytes received: {0}", (int)clientSocket.ReceiveBufferSize);
networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
clientsList.Add(dataFromClient, clientSocket);
broadcast(dataFromClient + " Joined ", dataFromClient, false);
Console.WriteLine(dataFromClient + " Joined chat room ");
handleClinet client = new handleClinet();
client.startClient(clientSocket, dataFromClient, clientsList);
}
clientSocket.Close();
serverSocket.Stop();
Console.WriteLine("exit");
Console.ReadLine();
}
public static void broadcast(string msg, string uName, bool flag)
{
foreach (DictionaryEntry Item in clientsList)
{
TcpClient broadcastSocket;
broadcastSocket = (TcpClient)Item.Value;
NetworkStream broadcastStream = broadcastSocket.GetStream();
Byte[] broadcastBytes = null;
if (flag == true)
{
broadcastBytes = Encoding.ASCII.GetBytes(uName + " says : " + msg);
}
else
{
broadcastBytes = Encoding.ASCII.GetBytes(msg);
}
broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
broadcastStream.Flush();
}
} //end broadcast function
}//end Main class
public class handleClinet
{
TcpClient clientSocket;
string clNo;
Hashtable clientsList;
public void startClient(TcpClient inClientSocket, string clineNo, Hashtable cList)
{
this.clientSocket = inClientSocket;
this.clientSocket.ReceiveBufferSize = 10025; // added
this.clNo = clineNo;
this.clientsList = cList;
Thread ctThread = new Thread(doChat);
ctThread.Start();
}
private void doChat()
{
int requestCount = 0;
byte[] bytesFrom = new byte[10025];
string dataFromClient = null;
Byte[] sendBytes = null;
string serverResponse = null;
string rCount = null;
requestCount = 0;
while ((true))
{
try
{
requestCount = requestCount + 1;
NetworkStream networkStream = clientSocket.GetStream();
networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
Console.WriteLine("From client - " + clNo + " : " + dataFromClient);
rCount = Convert.ToString(requestCount);
NotificationServer.broadcast(dataFromClient, clNo, true);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}//end while
}//end doChat
} //end class handleClinet
}//end namespace
Вы заметитеConsole.WriteLine, где я распечатываю количество полученных байтов.Я добавил это, когда получал исключение в следующем утверждении, что размер был вне диапазона.Это печатает число как 408 000 байтов.
Вот клиентская программа, немного измененная, потому что в моей версии VisualStudio 2017 для Mac я ничего не могу получить с помощью Windows Forms, чтобы даже создать проект в соответствии с примером.Так как я собираюсь поместить код в веб-приложение, как только разберусь в механике, я просто пытаюсь, чтобы клиент ввел свой идентификатор, затем набрал строку, чтобы сервер взял ее и ретранслировал.Другие клиенты будут делать то же самое из командной строки (по одному для каждого нового клиента).В настоящее время он принимает идентификатор пользователя и отправляет его.Я посылаю «Джон», и кажется, что он посылает «Джон $» в виде 5 байтов.
using System;
using System.Text;
using System.Net.Sockets;
using System.Threading;
namespace erc.bre
{
public class NotificationClient
{
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
NetworkStream serverStream = default(NetworkStream);
string readData = null;
string display = "";
string userName = "";
string message = "";
bool needsInvocation = true;
static NotificationClient nc = new NotificationClient();
public NotificationClient()
{
}
public static int Main(string[] args)
{
nc.msg();
return 0;
}
private void sendUserJoined()
{
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(message + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
}
private void InputReceived()
{
readData = "Conected to Chat Server ...";
msg();
clientSocket.Connect("127.0.0.1", 1025);
serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(userName + "$");
Console.WriteLine("Sending {0} bytes as '{1}'", outStream.Length, System.Text.Encoding.Default.GetString(outStream);
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
Thread ctThread = new Thread(getMessage);
ctThread.Start();
}
private void getMessage()
{
while (true)
{
serverStream = clientSocket.GetStream();
int buffSize = 0;
byte[] inStream = new byte[10025];
buffSize = clientSocket.ReceiveBufferSize;
serverStream.Read(inStream, 0, buffSize);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
readData = "" + returndata;
msg();
}
}
private void msg()
{
if (needsInvocation)
{
needsInvocation = false;
Console.Out.WriteLine("Starting Client");
Console.Out.WriteLine("Input your callerID: ");
nc.userName = nc.ReadLine();
nc.InputReceived();
nc.sendUserJoined();
nc.getMessage();
return;
}
display = display + Environment.NewLine + " >> " + readData;
Console.Out.WriteLine(display);
}
private string ReadLine()
{
string line = "";
char ch;
Console.WriteLine("Enter text when desired, 'enter' to end");
do
{
int x = Console.Read();
try
{
ch = Convert.ToChar(x);
if (ch == 0x0a)
{
return line;
}
}
catch (OverflowException e)
{
Console.WriteLine("{0} Value read = {1}.", e.Message, x);
ch = ' ';
}
line += ch;
} while (ch != 0x0a);
return line;
}
}
}
Консоль сервера показывает:
Сервер чата запущен .... Получено байт: 408300
Необработанное исключение: System.ArgumentOutOfRangeException: указанный аргумент вышел издиапазон допустимых значений.Имя параметра: размер в System.Net.Sockets.NetworkStream.Read (буфер Byte [], смещение Int32, размер Int32) в ConsoleApplication1.NotificationServer.Main (аргументы String []) в / Users / woo / Projects / erc-caml /bre / NotificationServer / NotificationServer.cs: строка 33 bash: строка 1: 45360 Прерывание прерывания: 6 "/ usr / local / share / dotnet / dotnet" "/ Пользователи / woo / Проекты / erc-caml / bre / NotificationServer / bin /Отладка / netcoreapp2.1 / NotificationServer.dll "
На консоли клиента отображается:
Запуск клиента Введите свой идентификатор вызывающего абонента: при желании введите текст, введите 'enter' в конец John
Подключен к серверу чата ... Отправка 5 байтов в виде 'John $'
Необработанное исключение: Необработанное Исключение: System.ArgumentOutOfRangeException: указанный аргумент находится вне диапазонадействительных значений.Имя параметра: размер в System.Net.Sockets.NetworkStream.Read (буфер Byte [], смещение Int32, размер Int32) в erc.bre.NotificationClient.getMessage () в / Users / woo / Projects / erc-caml / bre /NotificationMonitor / NotificationClient.cs: строка 60 в erc.bre.NotificationClient.msg () в /Users/woo/Projects/erc-caml/bre/NotificationMonitor/NotificationClient.cs:line 77
Почему сервервидя более 400 000 байтов?Это внутреннее поглощение материала, пока оно ожидает сообщения?Номер выглядит одинаково, независимо от того, как долго я жду, кстати.