Процессы C# общаются друг с другом с помощью сокетовC#

Место общения программистов C#
Ответить
Anonymous
 Процессы C# общаются друг с другом с помощью сокетов

Сообщение Anonymous »

Я написал приложение сокет-сервера, которое прослушивает и предоставляет услуги другим процессам, в серверном приложении — ту часть, которая прослушивает запросы:

Код: Выделить всё

void ListenToClients() {
while (true) {
IPEndPoint ipEP = new IPEndPoint(IPAddress.Any
, mcintPortRequests);
TcpListener listener = new TcpListener(ipEP);
try {
dicParams_t dicParams = null;
dicRegEx_t dicRegEx = null;
listener.Start();
if (mclient != null) {
mclient.Close();
}
mclient = listener.AcceptTcpClient();
mstream = mclient.GetStream();
if (mstream == null && !mstream.CanRead) {
listener.Stop();
return;
}
if (mstream.Read(msarybytRX, 0, msarybytRX.Length) == 0) {
return;
}
string strRX = Encoding.UTF8.GetString
(msarybytRX, 0, msarybytRX.Length);
//Trim off any null terminators
int intNT = strRX.IndexOf("\0");
if (intNT >= 0) {
strRX = strRX.Substring(0, intNT);
}
bool blnHTTPget, blnHTTPpost;
blnHTTPget = blnHTTPpost = false;
if (strRX.StartsWith(mcstrGET)) {
//Remove any framming information
const string cstrGetStartOfParams = "/?";
strRX = strRX.Substring(mcstrGET.Length);
int intStartOfParams = strRX
.IndexOf(cstrGetStartOfParams);
if (intStartOfParams >= 0) {
const string cstrGetEndOfParams = " HTTP/";
strRX = strRX.Substring(intStartOfParams
+ cstrGetStartOfParams.Length);
int intEODofParams = strRX.IndexOf
(cstrGetEndOfParams);
if (intEODofParams >= 0) {
strRX = strRX.Substring(0
, intEODofParams);
blnHTTPget = true;
}
}
} else if (strRX.StartsWith(mcstrPOST)) {
const string cstrPostStartOfParams = "\r\n\r\n";
strRX = strRX.Substring(mcstrPOST.Length);
int intStartOfParams = strRX
.IndexOf(cstrPostStartOfParams);
if (intStartOfParams >= 0) {
const string cstrPostEndOfParams = "\0";
strRX = strRX.Substring(intStartOfParams
+ cstrPostStartOfParams.Length);
int intEODofParams = strRX.IndexOf
(cstrPostEndOfParams);
if (intEODofParams >= 0) {
strRX = strRX.Substring(0
, intEODofParams);
blnHTTPpost = true;
}
}
}
string[] arystrParams = null;
if (blnHTTPget || blnHTTPpost) {
const char cchrParamDelimiter = '&';
arystrParams = strRX.Split
(cchrParamDelimiter);
} else {
//Remove whitespace
string strJSON = string.Empty;
bool blnInString = false;
for (int i = 0; i < strRX.Length; i++) {
if (strRX[i] == '\''
|| strRX[i] == '\"') {
blnInString = !blnInString;
} else if (blnInString == false
&& (strRX[i] == '\n'
|| strRX[i] == '\r'
|| strRX[i] == '\t'
|| strRX[i] == ' ')) {
continue;
}
strJSON += strRX[i];
}
//Not HTML GET or POST, is this a directy JSON
//exchange?
JsonObject jsonRX = JsonSerializer
.Deserialize(strJSON);
if (jsonRX != null) {
arystrParams = jsonRX
.Select(kvp =>  $"{kvp.Key}={kvp.Value}")
.ToArray();
}
}
if (arystrParams != null
&& arystrParams.Length > 0) {
dicParams = new dicParams_t();
dicRegEx = new dicRegEx_t();
foreach (string strParam in arystrParams) {
const char cchrAssignDelimiter = '=';
string[] arystrParam = strParam.Split
(cchrAssignDelimiter);
if (arystrParam.Length > 0) {
dicParams.Add(arystrParam[0]
, arystrParam[1]);
}
}
if (mfrmSetup == null) {
mfrmSetup = new clsSetupForm();
}
//Ensure the table is clear
mfrmSetup.table.Controls.Clear();
mfrmSetup.table.ColumnStyles.Clear();
mfrmSetup.table.RowStyles.Clear();
if (dicParams.Count > 0
&& mfrmSetup != null
&& mfrmSetup.Visible != true
&& dicParams.ContainsKey(mcstrFormTitle)) {
mfrmSetup.AcceptButton = mfrmSetup.OK;
mfrmSetup.CancelButton = mfrmSetup.Cancel;
foreach (kvpParams_t kvPair in dicParams) {
if (kvPair.Key
.CompareTo(mcstrFormTitle) == 0) {
mfrmSetup.Text = kvPair.Value;
continue;
}
if (kvPair.Key
.CompareTo(mcstrControls) != 0) {
continue;
}
//Translate JSON string into controls array
JsonArray aryControls = JsonSerializer
.Deserialize
(kvPair.Value);
//Process each record of the controls array
int intRow = 0;
foreach (JsonObject objCtrl in aryControls) {
string strLabel, strRegEx, strType;
JsonObject objParams = null;
strLabel = strRegEx = strType = null;
if (objCtrl[mcstrLabel] != null) {
strLabel = objCtrl[mcstrLabel]
.ToString();
}
if (!string.IsNullOrEmpty(strLabel)
&&  objCtrl[mcstrRegEx] != null) {
strRegEx = objCtrl[mcstrRegEx]
.ToString();
dicRegEx.Add(strLabel, strRegEx);
}
if (objCtrl[mcstrParams] != null) {
objParams = JsonSerializer
.Deserialize
(objCtrl[mcstrParams]);
}
if (objCtrl[mcstrType] != null) {
strType = objCtrl[mcstrType]
.ToString();
}
if (string.IsNullOrEmpty(strLabel)
|| string.IsNullOrEmpty(strType)) {
continue;
}
//Create and add label to table
Label lblKey = new Label();
lblKey.Text = strLabel + ":";
lblKey.TextAlign = ContentAlignment.MiddleRight;
mfrmSetup.table.Controls.Add(lblKey
, mcintColumnLabels, intRow);
mfrmSetup.table.ColumnStyles.Add
(new ColumnStyle(SizeType.Absolute
, lblKey.Width));
mfrmSetup.table.RowStyles.Add
(new RowStyle(SizeType.Absolute
, lblKey.Height));
//Create and add control to table
CheckBox cbCtrl = null;
ListBox lbCtrl = null;
TextBox tbCtrl = null;
Control ctrl = null;
if (strType.CompareTo(mcstrCtrlCheckBox) == 0) {
cbCtrl = new CheckBox();
if (cbCtrl != null) {
ctrl = cbCtrl;
}
} else if (strType.CompareTo(mcstrCtrlListBox) == 0) {
lbCtrl = new ListBox();
if (lbCtrl != null) {
ctrl = lbCtrl;
}
} else if (strType.CompareTo(mcstrCtrlTextBox) == 0) {
tbCtrl = new TextBox();
if (tbCtrl != null) {
if (!string.IsNullOrEmpty(strRegEx)) {
tbCtrl.TextChanged += TextBoxChanged;
tbCtrl.Tag = strRegEx;
}
ctrl = tbCtrl;
}
}
if (ctrl != null) {
//Add control to table
mfrmSetup.table.Controls.Add(ctrl
, mcintColumnControls, intRow);
intRow++;
ctrl.Anchor = AnchorStyles.None;
//Apply parameters
foreach (var jsonNode in objParams) {
string strKey = jsonNode.Key;
int intTmp;
if (strKey.CompareTo(mcstrName) == 0) {
//Set name first, it helps to identify control when debugging
ctrl.Name = jsonNode.Value.ToString();
continue;
}
if (strKey.CompareTo(mcstrCheckAlign) == 0
&&  cbCtrl != null) {
string strCheckAlign = jsonNode.Value
.ToString();
if (strCheckAlign
.CompareTo(mcstrCenter) == 0) {
cbCtrl.CheckAlign = ContentAlignment
.MiddleCenter;
} else if (strCheckAlign
.CompareTo(mcstrLeft) == 0) {
cbCtrl.CheckAlign = ContentAlignment
.MiddleLeft;
} else if (strCheckAlign
.CompareTo(mcstrRight) == 0) {
cbCtrl.CheckAlign = ContentAlignment
.MiddleRight;
}
continue;
}
if (strKey.CompareTo(mcstrHeight) == 0) {
if (int.TryParse(jsonNode.Value.ToString()
, out intTmp)) {
ctrl.Height = intTmp;
}
continue;
}
if (strKey.CompareTo(mcstrTextAlign) == 0
&&  tbCtrl != null) {
string strTextAlign = jsonNode.Value
.ToString();
if (strTextAlign
.CompareTo(mcstrCenter) == 0) {
tbCtrl.TextAlign = HorizontalAlignment
.Center;
} else if (strTextAlign
.CompareTo(mcstrLeft) == 0) {
tbCtrl.TextAlign = HorizontalAlignment
.Left;
} else if (strTextAlign
.CompareTo(mcstrRight) == 0) {
tbCtrl.TextAlign = HorizontalAlignment
.Right;
}
continue;
}
if (strKey.CompareTo(mcstrText) == 0) {
ctrl.Text = jsonNode.Value.ToString();
continue;
}
if (strKey.CompareTo(mcstrWidth) == 0) {
if (int.TryParse(jsonNode.Value.ToString()
, out intTmp)) {
ctrl.Width = intTmp;
}
continue;
}
}
}
}
}
DialogResult result = mfrmSetup.ShowDialog();
if (result != DialogResult.OK) {
continue;
}
Console.WriteLine("HERE!");
}
}
//Then, update the code to use JsonObject correctly:
JsonObject objResponse = new JsonObject();
MemoryStream memStream = new MemoryStream
(msarybytRX, 0, msarybytRX.Length);
StreamWriter streamWriter = new StreamWriter(memStream);
streamWriter.Flush();
Console.WriteLine(strRX);
} catch (Exception ex) {
Console.WriteLine($"ERROR: {ex.Message}");
} finally {
listener.Stop();
}
}
}
public Task Start() {
new Thread(async () => ListenToClients()).Start();
return Task.CompletedTask;
}
Когда форма редактируется и клиенту доступна дополнительная информация, клиент отправляет дополнительную информацию на сервер, которая получается задачей, созданной при изменении текстового поля формы.

Код: Выделить всё

void TextBoxChanged(object obj, EventArgs args) {
TextBox tb = (TextBox)obj;
if (tb != null && !string.IsNullOrEmpty((string)tb.Tag)) {
string strRegEx = (string)tb.Tag;
if ((new Regex(strRegEx)).IsMatch(tb.Text)) {
tb.ForeColor = Color.Gray;
if (mstrLastSlot == null) {
mstrLastSlot = string.Empty;
}
if (tb.Text.CompareTo(mstrLastSlot) != 0) {
// Request information from Optix about this slot
if (mclient.Connected == true
&& mstream != null
&& mstream.CanWrite) {
int intSlot = 0;
if (!int.TryParse(tb.Text, out intSlot)
|| intSlot < 0) {
return;
}
JsonObject objTX = new JsonObject();
objTX[mcstrMsgCode] = mcuintMsgCodeRequestTags;
objTX[mcstrSlot] = intSlot;
string strTX = objTX.ToString();
byte[] arybytTX = Encoding.ASCII.GetBytes(strTX);
if (arybytTX != null) {
mstream.Write(arybytTX, 0, arybytTX.Length);
// Wait for response
const int cintWaitForResponseMS = 5000;
var WaitForResponse = Task.Run(() =>  {
JsonObject objRX;
try {
if (mstream == null && !mstream.CanRead) {
return;
}
if (mstream.Read(msarybytRX, 0, msarybytRX.Length) == 0) {
return;
}
objRX = JsonSerializer.Deserialize(msarybytRX);
if (objRX != null) {
Console.WriteLine("HACK");
}
} catch (Exception ex) {
Console.WriteLine($"ERROR: {ex.Message}");
}
});
if (WaitForResponse.Wait(cintWaitForResponseMS)) {
// Response received
} else {
throw new TimeoutException("The operation has timed out.");
}
}
}
}
} else {
tb.ForeColor = Color.Red;
}
}
}
Проблема, с которой я столкнулся, — это исключение при получении второго пакета от клиента:

Код: Выделить всё

{"'\"' is invalid after a single JSON value. Expected end of data. Path: $ | LineNumber: 0 | BytePositionInLine: 643."}
Это клиентский код, который отправляет пакет, вызывающий вышеуказанное исключение:

Код: Выделить всё

string strJSON = jsonTags.ToJsonString();
Console.WriteLine(strJSON);
byte[] arybytJSON = Encoding.UTF8.GetBytes(strJSON);
if (ssckBMLFS.Send(arybytJSON) > 0) {
...
Из консоли strJSON:

Код: Выделить всё

{"slot":3,"count":16,"Data":["00, Board Magazine Walker (LHS)\r\nSensor (String)","01, Board Magazine Walker (RHS)\r\nSensor (String)","02, Spare (String)","03, Board Magazine Low Level Sensor (String)","04, Spare (String)","05, Board Arm\r\nBrake Release\r\nButton (String)","06, Board Arm Servo Homing Sensor (String)","07, Spare (String)","08, Spare (String)","09, Spare (String)","10, Board Down Sensor (String)","11, Spare (String)","12, Bottom Flap Retainer Fully Up Sensor (String)","13, Spare (String)","14, Board Magazine Support (Auto) Selector Switch (String)","15, Board Magazine Support (Refill) Selector Switch (String)"]}
Я проверил вышеизложенное на https://jsonlint.com/, и ответ: JSON действителен!
Может ли кто-нибудь увидеть, что может быть не так в блоке принимающей задачи?

Подробнее здесь: https://stackoverflow.com/questions/798 ... ng-sockets
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»