Reading from COM port with BaseStream.BeginRead and getting a substring - c#

Im trying to read from a com port, this is my code
public string HouseState()
{
string state = string.Empty;
if (!Variables.portBusy)
{
// Begin communications
var blockLimit = 13;
openSerial();
byte[] buffer = new byte[blockLimit];
Action kickoffRead = null;
kickoffRead = delegate
{
serialPort.BaseStream.BeginRead(buffer, 0, buffer.Length, delegate (IAsyncResult ar)
{
try
{
int actualLength = serialPort.BaseStream.EndRead(ar);
byte[] received = new byte[actualLength];
Buffer.BlockCopy(buffer, 0, received, 0, actualLength);
state += System.Text.Encoding.UTF8.GetString(received);
//MessageBox.Show(state);
}
catch (IOException exc)
{
//handleAppSerialError(exc);
}
if (state.Count() <= 13)
kickoffRead();
}, null);
};
kickoffRead();
}
MessageBox.Show(state);
var index = state.IndexOf("R");
var command = string.Empty;
if (index >= 0)
command = state.Substring(index, 13);
return command;
}
What im trying to get is a string that starts with R and has 13 characters. Because sometimes the port sends half the string i do this: if (state.Count() <= 13)
But while inside BaseStream the state string gets what i want, when i try to read the string of state, it appears empty. The MessageBox shows an empty string.
why this is happening?

The BeginRead method of SerialPort.BaseStream is asynchronous so by the moment you're getting to MessageBox.Show(state); the actual read may have not completed yet and state is still empty. You need to wait until all necessary data is read:
// .....................
var readComplete = new ManualResetEvent(false);
kickoffRead = delegate
{
serialPort.BaseStream.BeginRead(buffer, 0, buffer.Length, delegate (IAsyncResult ar)
{
// ...................
if (state.Count() <= 13)
kickoffRead();
else
readComplete.Set();
}, null);
};
kickoffRead();
readComplete.WaitOne();
// ......................
Having said that BeginRead/EndRead based async reading is superseded by ReadAsync one. And based on your original snippet even synchronous read is acceptable in your case. You may find examples for both in the answers to this question: C# Async Serial Port Read

Related

C# Deadlock in Named Pipe

Im stuck. I have joined the project that uses Named Pipes, and have lets say "not ideal architecture". And seems like I accidentally received a deadlock:(
The logic is following. There is Named Pipe. Client and Server model. On server part there is a loop, that always pings named pipe and process what client sends, sometimes sending back responses.
On Client side of my pipe, I have following method, from other developer, that is being used to send request to server and receive and return the response.
private object locker = new Object();
private string ListenOnce(string msg)
{
Debug.WriteLine("Will listen for message " + msg);
string msgFrom = "";
if (run) {
string toReturn = "";
lock (locker) {
sw.WriteLine(msg); //Writing command to the pipes
stream.WaitForPipeDrain(); //Waiting for another process to read the command
msgFrom = sr.ReadLine(); //Reading
toReturn = sr.ReadLine ();
if (toReturn.Contains('¥'))
{
string[] split = toReturn.Split('¥');
if (split.Length > 1)
{
var roomNames = this.connection.application.GameCache.GetRoomNames();
for (int i = 1; i < split.Length; i++)
{
string[] split2 = split[i].Split('¶');
if (split2.Length > 1)
{
string accountName = split2[0];
int offenderActorID = int.Parse(split2[1]);
string offenderRoomName = split2[2];
foreach (var roomName in roomNames)
{
Room room;
if (this.connection.application.GameCache.TryGetRoomWithoutReference(roomName, out room))
{
Game game = room as Game;
if (game != null && game.Name == offenderRoomName)
{
GameClientPeer peer = (GameClientPeer)game.ActorsManager.ActorsGetActorByNumber(offenderActorID).Peer;
if (peer != null)
{
peer.KickPlayer();
}
}
}
}
}
}
}
}
}
if (toReturn.Contains('¥'))
{
return toReturn.Split('¥')[0];
}
else
{
return toReturn;
}
}
return "";
}
The problem is - in some cases I cant receive response from pipe right when requested, and need to start what I called here "poller". This is a task, that loops 5 times, and during those 5 times "polls" the pipe through this ListenOnce method.
private void PollTargets()
{
timer.Dispose();
Debug.WriteLine("Going to start polling");
Task.Factory.StartNew(() => {
int runCount = 0;
while (true)
{
runCount++;
PipeOperation request = new PipeOperation(Consts.Pipes.RequestTargets, uniqueID);
string responseStr = unityConnection.client.SendMessage(JsonConvert.SerializeObject(request));
Debug.WriteLine("Task is running, response is " + responseStr);
if (!string.IsNullOrEmpty(responseStr))
{
try
{
PipeOperation pipeResponse = JsonConvert.DeserializeObject<PipeOperation>(responseStr);
if (!string.IsNullOrEmpty(pipeResponse.Payload))
{
GrenadeExplosionData explosionData = JsonConvert.DeserializeObject<GrenadeExplosionData>(pipeResponse.Payload);
if (explosionData != null)
{
//probably need to invoke that in main thread
DealDamage(explosionData);
//isRunning = false;
Debug.WriteLine("Received nice response, will damage targets");
break;
}
}
}
catch (Exception exc)
{
Debug.WriteLine("Something went wrong while polling...");
Debug.WriteLine(exc.Message);
break;
}
}
if (runCount > 5)
{
Debug.WriteLine("run count exceed " + runCount.ToString());
break;
}
}
RemoveGrenadeFromUnityConnection();
});
}
I am starting poller when the Grenade explodes, from timer like that:
timer = new System.Threading.Timer((obj) =>
{
PollTargets();
},
null, 4000, System.Threading.Timeout.Infinite);
And thats it. After people play 2-3 hrs. Seems like I receive a deadlock. It should be taken into account that there might be many grenades on server who starts that poller, so probably it just goes mad at some point over there.
Pls help, Im stuck with that. Who has ideas?
We should keep in mind, that
sw.WriteLine(msg); //Writing command to the pipes
stream.WaitForPipeDrain();
msgFrom = sr.ReadLine(); //Reading
toReturn = sr.ReadLine ();
should be used only by one thread at a time, as stream might be read only from one source.
There are several calls to ListenOnce from the code, but not a lot. One is being fired every 4 minutes.The rest ones are not constant, but conditional.
Hope somebody would see where is a mistake here...
Found what locks everything...However, it does not help a lot:)
Its
stream.WaitForPipeDrain();
it tries to read another end of pipe, but because of there is no timeouts in message mode, it just hangs for ever..

Write to USB PORT C# using LibUsbDotNet C# USB Library

I want to write some data to a USB port and receive an answer from it.
I actually used the same
string cmdLine = "#00WD3000C82B*\r";
and sent it to the same machine with the SerialPort object and by using rs235 port.
its do well.. and I got the right answer
using these methods:
omronAX.WriteAction("3000", 200.ToString("0000"));
public void WriteAction(string DM_address, string Data)
{
write_action(DM_address, Data);
}
private void write_action(string DM_address, string Data)
{
GotData = "";
Puredata = "";
EndCode = "";
try
{
int ErCd = Write_2_port("WD", DM_address, Data);
if (ErCd != 0) { return; }
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private int Write_2_port(string cod_cmd, string Addr, string Data2write)
{
DReady = false;
out_data = "";
end_c = "";
char cr = Convert.ToChar(13);
string cmd = "", Dat1 = "", Dat2 = "";
Mess = "";
Dat2 = Data2write;
if (Addr.Trim().Length > 0)
{
try
{
Dat1 = String.Format("{0:0000}", Convert.ToInt16(Addr));
}
catch (FormatException ex)
{
Mess = ex.Message;
return 1;
}
catch (OverflowException ex1)
{
Mess = ex1.Message;
return 3;
}
}
int.TryParse(Dat2, out int hex);
string hexValue = hex.ToString("X");
cmd = "#" + BakN + cod_cmd + Dat1 + hexValue ;
string send2port = cmd + Checksm(cmd) + "*" + cr;
SentCommand = send2port;
try
{
// if (Sport.IsOpen == false) { Sport.Open(); }
locking = true;
Sport.WriteTimeout = 5000;
Sport.WriteLine(send2port);
int i = 0;
while (locking)
{
if (i++ == 500)
{
throw new TimeoutException("יתכן שיש בעיות תקשורת עם המערכת.");
}
Thread.Sleep(10);
}
// T:System.ArgumentNullException:
// The str parameter is null.
//
// T:System.InvalidOperationException:
// The specified port is not open.
//
// T:System.TimeoutException:
// The System.IO.Ports.SerialPort.WriteLine(System.String) method could not write
// to the stream.
}
catch (TimeoutException ex)
{
Mess = ex.Message;
throw ex;
}
catch (Exception ex)
{
Mess = ex.Message;
return 2;
}
return 0;
}
for the next code, I try using USB port and write to it the same line...
But I got nothing when I read the answer back and I got (bytesRead = 0)
in my bytesWritten, I got 15...
using System;
using System.Text;
using System.Text.RegularExpressions;
using LibUsbDotNet;
using LibUsbDotNet.Main;
namespace Examples
{
internal class ReadWrite
{
public static UsbDevice MyUsbDevice;
#region SET YOUR USB Vendor and Product ID!
public static UsbDeviceFinder MyUsbFinder = new UsbDeviceFinder(0x0590,0x005B);
#endregion
public static void Main(string[] args)
{
ErrorCode ec = ErrorCode.None;
try
{
// Find and open the USB device.
MyUsbDevice = UsbDevice.OpenUsbDevice(MyUsbFinder);
// If the device is open and ready
if (MyUsbDevice == null) throw new Exception("Device Not Found.");
// If this is a "whole" usb device (libusb-win32, linux libusb)
// it will have an IUsbDevice interface. If not (WinUSB) the
// variable will be null indicating this is an interface of a
// device.
IUsbDevice wholeUsbDevice = MyUsbDevice as IUsbDevice;
if (!ReferenceEquals(wholeUsbDevice, null))
{
// This is a "whole" USB device. Before it can be used,
// the desired configuration and interface must be selected.
// Select config #1
wholeUsbDevice.SetConfiguration(1);
// Claim interface #0.
wholeUsbDevice.ClaimInterface(0);
}
// open read endpoint 1.
UsbEndpointReader reader = MyUsbDevice.OpenEndpointReader(ReadEndpointID.Ep01);
// open write endpoint 1.
UsbEndpointWriter writer = MyUsbDevice.OpenEndpointWriter(WriteEndpointID.Ep01);
// Remove the exepath/startup filename text from the begining of the CommandLine.
//string cmdLine = Regex.Replace(Environment.CommandLine, "^\".+?\"^.*? |^.*? ", "", RegexOptions.Singleline);
string cmdLine = "#00WD3000A11*\r";
if (!String.IsNullOrEmpty(cmdLine))
{
int bytesWritten;
ec = writer.Write(Encoding.Default.GetBytes(cmdLine), 20000000, out bytesWritten);
if (ec != ErrorCode.None) throw new Exception(UsbDevice.LastErrorString);
byte[] readBuffer = new byte[1024];
while (ec == ErrorCode.None)
{
int bytesRead;
// If the device hasn't sent data in the last 100 milliseconds,
// a timeout error (ec = IoTimedOut) will occur.
ec = reader.Read(readBuffer, 100, out bytesRead);
if (bytesRead == 0) throw new Exception("No more bytes!");
// Write that output to the console.
Console.Write(Encoding.Default.GetString(readBuffer, 0, bytesRead));
}
Console.WriteLine("\r\nDone!\r\n");
}
else
throw new Exception("Nothing to do.");
}
catch (Exception ex)
{
Console.WriteLine();
Console.WriteLine((ec != ErrorCode.None ? ec + ":" : String.Empty) + ex.Message);
}
finally
{
if (MyUsbDevice != null)
{
if (MyUsbDevice.IsOpen)
{
// If this is a "whole" usb device (libusb-win32, linux libusb-1.0)
// it exposes an IUsbDevice interface. If not (WinUSB) the
// 'wholeUsbDevice' variable will be null indicating this is
// an interface of a device; it does not require or support
// configuration and interface selection.
IUsbDevice wholeUsbDevice = MyUsbDevice as IUsbDevice;
if (!ReferenceEquals(wholeUsbDevice, null))
{
// Release interface #0.
wholeUsbDevice.ReleaseInterface(0);
}
MyUsbDevice.Close();
}
MyUsbDevice = null;
// Free usb resources
UsbDevice.Exit();
}
// Wait for user input.
Console.ReadKey();
}
}
}
}
I have no idea and I am doing wrong, thanks.
I recommend using Usb.Net (https://github.com/MelbourneDeveloper/Device.Net) instead of LibUsb. The problem with LibUsb is that is just wraps WinUSB calls. So, you are deploying an extra C dll (LibUsb) that just points to an existing Windows C DLL. LibUsb is good if you want to keep the code cross platform with Linux, but otherwise, there's not much point.
Here is sample WinUsb code (https://github.com/MelbourneDeveloper/Device.Net/blob/master/src/Usb.Net/Windows/WindowsUsbDevice.cs)
public override Task InitializeAsync()
{
Dispose();
int errorCode;
if (string.IsNullOrEmpty(DeviceId))
{
throw new WindowsException($"{nameof(DeviceDefinition)} must be specified before {nameof(InitializeAsync)} can be called.");
}
_DeviceHandle = APICalls.CreateFile(DeviceId, (APICalls.GenericWrite | APICalls.GenericRead), APICalls.FileShareRead | APICalls.FileShareWrite, IntPtr.Zero, APICalls.OpenExisting, APICalls.FileAttributeNormal | APICalls.FileFlagOverlapped, IntPtr.Zero);
if (_DeviceHandle.IsInvalid)
{
//TODO: is error code useful here?
errorCode = Marshal.GetLastWin32Error();
if (errorCode > 0) throw new Exception($"Device handle no good. Error code: {errorCode}");
}
var isSuccess = WinUsbApiCalls.WinUsb_Initialize(_DeviceHandle, out var defaultInterfaceHandle);
HandleError(isSuccess, "Couldn't initialize device");
var bufferLength = (uint)Marshal.SizeOf(typeof(USB_DEVICE_DESCRIPTOR));
isSuccess = WinUsbApiCalls.WinUsb_GetDescriptor(defaultInterfaceHandle, WinUsbApiCalls.DEFAULT_DESCRIPTOR_TYPE, 0, 0, out _UsbDeviceDescriptor, bufferLength, out var lengthTransferred);
HandleError(isSuccess, "Couldn't get device descriptor");
byte i = 0;
//Get the first (default) interface
var defaultInterface = GetInterface(defaultInterfaceHandle);
_UsbInterfaces.Add(defaultInterface);
while (true)
{
isSuccess = WinUsbApiCalls.WinUsb_GetAssociatedInterface(defaultInterfaceHandle, i, out var interfacePointer);
if (!isSuccess)
{
errorCode = Marshal.GetLastWin32Error();
if (errorCode == APICalls.ERROR_NO_MORE_ITEMS) break;
throw new Exception($"Could not enumerate interfaces for device {DeviceId}. Error code: { errorCode}");
}
var associatedInterface = GetInterface(interfacePointer);
_UsbInterfaces.Add(associatedInterface);
i++;
}
IsInitialized = true;
RaiseConnected();
return Task.CompletedTask;
}
However, I did submit this sample to LibUsbDotNet and it's now the accepted Read/Write sample there (https://github.com/LibUsbDotNet/LibUsbDotNet/blob/master/src/Examples/Read.Write/ReadWrite.cs):
public static void Main(string[] args)
{
using (var context = new UsbContext())
{
context.SetDebugLevel(LogLevel.Info);
//Get a list of all connected devices
var usbDeviceCollection = context.List();
//Narrow down the device by vendor and pid
var selectedDevice = usbDeviceCollection.FirstOrDefault(d => d.ProductId == ProductId && d.VendorId == VendorId);
//Open the device
selectedDevice.Open();
//Get the first config number of the interface
selectedDevice.ClaimInterface(selectedDevice.Configs[0].Interfaces[0].Number);
//Open up the endpoints
var writeEndpoint = selectedDevice.OpenEndpointWriter(WriteEndpointID.Ep01);
var readEnpoint = selectedDevice.OpenEndpointReader(ReadEndpointID.Ep01);
//Create a buffer with some data in it
var buffer = new byte[64];
buffer[0] = 0x3f;
buffer[1] = 0x23;
buffer[2] = 0x23;
//Write three bytes
writeEndpoint.Write(buffer, 3000, out var bytesWritten);
var readBuffer = new byte[64];
//Read some data
readEnpoint.Read(readBuffer, 3000, out var readBytes);
}
}
I had an issue getting my device to connect with another library because I was using upper case for alphabetic characters in the VID/PID. Have you tried using lower case ("0x005b" instead of "0x005B")?

Socket not reading all the packets that arrive

I am working on a C# TCP client and monitoring my packets using Microsoft Network Monitor. There is a server that's basically a black box sends an N amount of packets (right now it's in the order of 10-20) with a delay of 0,1 ms to 1 ms between each of them and the next one.
The packets that are read by my client are in order and of course most arrive in larger chunks than appear on Network Monitor since TCP receives the stream. My problem is some packets fail to arrive (I did check the previous chunk of information to make sure it's not there. They aren't stored in the wrong order either.).
So is it possible that my client is missing some of the information somehow? Are the packets being sent too frequently? Sadly I cannot tamper with their frequency. I add here some of my code, if you could enlighten me as to why packets that arrive are not read and how to solve this I would be most grateful.
This is where I first call BeginReceive:
private static void AcceptCallback(IAsyncResult result)
{
ConnectionInfo connection = new ConnectionInfo();
MensajeRecibido msj = new MensajeRecibido();
try
{
// Finish Accept
Socket s = (Socket)result.AsyncState;
connection.Socket = s.EndAccept(result);
msj.workSocket = connection.Socket;
connection.Socket.Blocking = false;
connection.Buffer = new byte[255];
lock (connections) connections.Add(connection);
// Start Receive
connection.Socket.BeginReceive(msj.buffer, 0,
msj.buffer.Length, SocketFlags.None,
new AsyncCallback(ReceiveCallback), msj);
// Start new Accept
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), result.AsyncState);
}
catch (SocketException exc)
{
//Log here
}
catch (Exception exc)
{
//Log here
}
}
This is the callback:
private async static void ReceiveCallback(IAsyncResult result)
{
MensajeRecibido mensaje = new MensajeRecibido();
mensaje = (MensajeRecibido)result.AsyncState;
try
{
mensaje.workSocket.EndReceive(result);
mensaje.EstaCompleto();
mensaje.workSocket.BeginReceive(mensaje.buffer, 0,
mensaje.buffer.Length, SocketFlags.None,
new AsyncCallback(ReceiveCallback), mensaje);
}
catch (SocketException)
{
//Log
}
catch (Exception)
{
//Log
}
}
And this is the method EstaCompleto() which basically converts the message and adds it to a list. (It returns true or false because it's actually meant to go in an if clause but until I get rid of this problem that really serves no purpose)
public bool EstaCompleto()
{
MensajeActual = Destuffing(ByteToFrame_Decoder(buffer)); //This translates the message to an understandable string
Mensajes.Enqueue(MensajeActual);
if(MensajeActual.Contains("<ETX>"))
{
return true;
}
else return false;
}
Edit 25/3/15:
Here's the rest of the class MensajeRecibido.
public class MensajeRecibido
{
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 25500;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
public string UltimoMensajeLeido = "0";
public string MensajeActual = "0";
public Queue<string> Mensajes = new Queue<string>();
public IPAddress IPRack;
//*******************************************************************
public bool EstaCompleto()
///See code in the previous sample
//*******************************************************************
public string ByteToFrame_Decoder(byte[] frame)
{
string answer = null;
UTF8Encoding ObjDecoder = new System.Text.UTF8Encoding();
char[] array_chares = new char[frame.Length];
string msj_neg = null;
string titlemsg = "Atención";
try
{
int cant = ObjDecoder.GetChars(frame, 0, frame.Length, array_chares, 0);
}
catch (EncoderFallbackException EncFbackEx)
{
msj_neg = "No hay comunicación";
// System.Windows.Forms.MessageBox.Show(msj_neg, titlemsg, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
answer = decode_string(array_chares);
return answer;
} // fin método ByteToFrame_Decoder()
//*******************************************************************
public string Destuffing(string msjstuff)
{
string destuffed = null;
string matched = null;
string original = null;
int largo = msjstuff.Length;
for (int i = 0; i < (largo - 1); i++)
{
matched = msjstuff.Substring(i, 2);
original = msjstuff.Substring(i, 1);
if (original != " ")
{
switch (matched)
{
case "EX":
{ original = "D"; i++; } break;
case "ex":
{ original = "d"; i++; } break;
case "EE":
{ original = "E"; i++; } break;
case "ee":
{ original = "e"; i++; } break;
case " ":
{ original = ""; i += 2; } break;
}
destuffed = destuffed + original;
}
else
{
i++;
}
}
destuffed = destuffed + ">";
return destuffed;
} //fin método Destuffing()
//*******************************************************************
public static string decode_string(char[] ArrChar)
{
string text = null;
string reply = null;
foreach (char letter in ArrChar)
{
int value = Convert.ToInt32(letter);
string hexOutput = String.Format("{0:X}", value); // Convert the decimal value to a hexadecimal value in string form.
switch (hexOutput)
{
case "20":
text = " ";
break;
case "1":
text = "<SOH>";
break;
case "2":
text = "<STX>";
break;
case "3":
text = "<ETX>";
break;
case "4":
text = "<EOT>";
reply = reply + text;
goto Finish;
case "5":
text = "<ENQ>";
break;
case "6":
text = "<ACK>";
break;
case "15":
text = "<NAK>";
break;
case "17":
text = "<ETB>";
break;
case "1E":
text = "<RS>";
break;
/*case "23":
text = "#";
break;
case "24":
text = "$";
break;
case "26":
text = "&";
break;*/
default:
text = letter.ToString();
break;
}
reply = reply + text;
}
Finish: ; //salimos del foreach
return reply;
} //fin método decode_string()
//*******************************************************************
}
Without a good, minimal, complete code example that reliably demonstrates the problem, it's impossible to provide an exact fix for the bug.
However, from this statement in your ReceiveCallback() method, it's clear what the problem is:
mensaje.workSocket.EndReceive(result);
The EndReceive() method returns a byte count for a reason: there is no guarantee of the number of bytes that will be received.
Network programming novices generally complain about two different behaviors:
Their code only receives part of a "packet" (or "message", or similar terminology).
Their code fails to receive some of the "packets" which were sent.
Both problems stem from a single source: the failure to understand that in the TCP protocol, there is no such thing as a "packet".
It's up to the application to define a message boundary. All that TCP gives you is a guarantee that if the bytes sent are in fact received, they will be received in the same order in which they were sent, and if any given byte is received, all of the previously sent bytes were also received (i.e. no gaps in the data).
Problem #1 above happens when TCP delivers only part of what the novice programmer sent as a "packet". This is perfectly legal behavior on TCP's part, and it's up to the application to keep track of the data received so far and to figure out when it's received a whole "packet".
Problem #2 (which is what you're experiencing) happens when TCP delivers two or more "packets" in a single receive operation. Again, this is perfectly legal on TCP's part, and it's up to the application to process the received data and identify where one "packet" ends and the next begins.
The first step to doing all of this correctly is to actually copy the return value of the EndReceive() method to a variable, and then to use that value as part of processing the received data. Since your code example doesn't save the value anywhere, or even look at it at all, I can guarantee that you aren't correctly handling the "packet" boundaries in your data.
How should you handle those boundaries? I have no idea. It depends on how you are sending the data, and how you want to process the results. Without a complete code example (as described in the link I provided above), it's not possible to address that. Do note however that there are a large number of examples out there for how to do it correctly. Hopefully now that you know what to look for, you will be able to come up with a fix yourself. If not, feel free to create a good code example and post a new question asking for help with that.

c# If statement always returns false

I'm currently developing a small server/client application for a personal project. The server is meant to be run in Linux under Mono while the client is being run from a Windows PC.
I have an issue where I am passing data to the server (In this case string value of "on" and "off") however an if statement is always returning a false value.
The code from the server is as follows
public void startServer() {
TcpListener listen = new TcpListener(serverIP, 10000);
listen.Start();
Console.Clear();
Console.WriteLine("IP Address = {0}", serverIP.ToString());
Console.WriteLine("Server is listening for connection");
Socket a = listen.AcceptSocket();
Console.WriteLine("Connection from {0}", a.RemoteEndPoint);
ASCIIEncoding respond = new ASCIIEncoding();
a.Send(respond.GetBytes("You are connected to LED Control Server"));
bool keepListening = true;
while (keepListening) {
byte[] b = new byte[1000];
a.Receive(b);
Console.WriteLine("Message Received from {0}, string: {1}", a.RemoteEndPoint, recData(b));
string serverMsg = procIns(recData(b));
a.Send(respond.GetBytes(serverMsg));
}
}
private string recData(byte[] b) //receiving data from the client {
int count = b.Length;
string message = "";
for (int a = 0; a < count; a++) {
message += Convert.ToChar(b[a]);
}
return message;
}
private string procIns(string instruction) {
string returnMsg;
Console.WriteLine(instruction.ToLower());
if (instruction.ToLower() == "on") {
FileGPIO gpio = new FileGPIO();
gpio.OutputPin(FileGPIO.enumPIN.gpio17, true);
returnMsg = "GPIO 17 1";
} else if (instruction.ToLower() == "off") {
FileGPIO gpio = new FileGPIO();
gpio.OutputPin(FileGPIO.enumPIN.gpio17, false);
returnMsg = "GPIO 17 0";
} else {
returnMsg = "Invalid Command";
}
return returnMsg;
}
The cause for the if statement in procIns method returning false is escaping me, if anyone could offer any advice I would appreciate it!
I would guess it would have to be padded spaces. Try this instead...
if (instruction.Trim().ToLower() == "on")
while (keepListening) {
byte[] b = new byte[1000];
int bytesRcvd = a.Receive(b);
Console.WriteLine("Message Received from {0}, string: {1}", a.RemoteEndPoint, recData(b));
string serverMsg = procIns(recData(b, bytesRcvd ));
a.Send(respond.GetBytes(serverMsg));
}
a.Receive(b) method returns number of bytes received. You can store the value in some variable and pass the variable to recData method.
private string recData(byte[] b, int bytesRcvd) {
string message = "";
for (int a = 0; a < bytesRcvd; a++) {
message += Convert.ToChar(b[a]);
}
return message;
}
The number of bytes received will help in truncating the extra values in byte array.

How to convert byte into Boolean

I want to convert a byte into Boolean. This is the code:
String text = textBox1.Text;
UdpClient udpc = new UdpClient(text,8899);
IPEndPoint ep = null;
while (true)
{
MessageBox.Show("Name: ");
string name = "Connected";
if (name == "") break;
byte[] sdata = Encoding.ASCII.GetBytes(name);
udpc.Send(sdata, sdata.Length);
if (udpc.Receive(ref ep)=null)
{
// MessageBox.Show("Host not found");
}
else
{
byte[] rdata = udpc.Receive(ref ep);
string job = Encoding.ASCII.GetString(rdata);
MessageBox.Show(job);
}
}
I want to convert this line of code into a Boolean:
udpc.Receive(ref ep);
You don't want to just compare the result with null at all... that way you would lose the actual data, and then call Receive again, effectively skipping the packet.
You should use:
byte[] data = udpc.Receive(ref ep);
if (data == null)
{
// Whatever
}
else
{
MessageBox.Show(Encoding.ASCII.GetBytes(data));
}
Also note that this code is broken:
string name = "Connected";
if (name == "") break;
How can name possibly be an empty string when you've just set it to "Connected"?
The UdpClient is naturally blocking until bytes are received.
This means that you shouldn't get data at all, assuming that you're looking for a way to indicate if you have received data, then once you move past the udpc.Recieve, you should return true.
I would also consider changing the code a bit as you will have some compilation issues with the = null statement as this does not translate into a compilable code expression.
There is also a problem with your if else statement as you're attempting to read from the UDP client which would consume the sent data.
Personally I would opt for a UDP socket, but in order to get you rolling I would change the code to something like this:
String text = textBox1.Text;
UdpClient udpc = new UdpClient(text,8899);
IPEndPoint ep = null;
while (true)
{
MessageBox.Show("Name: ");
string name = "Connected";
if (name == "") break; //This will never happen because you have already set the value
byte[] sdata = Encoding.ASCII.GetBytes(name);
int dataSent = 0;
try
{
dataSent = udpc.Send(sdata, sdata.Length);
}
catch(Exception e)
{
dataSent = 0;
//There is an exception. Probably the host is wrong
}
if (dataSent > 0)
{
try
{
byte[] rdata = udpc.Receive(ref ep);
if(rdata!=null && rdata.Length > 0)
{
string job = Encoding.ASCII.GetString(rdata);
MessageBox.Show(job)
//True here as we managed to recieve without going to the catch statement
//and we actually have data in the byte[]
}
else
{
MessageBox.Show("We did not recieve any data");
//False here, because the array was empty.
}
}
catch(Exception udpe)
{
//False here as we had a socket exception or timed out
MessageBox.Show(udpe.ToString());
}
}
}

Categories