I have 2 applications running on a WinCE 6.0 device and both are written on Visual C#, I need to pass info between the 2 apps and do some actions inside, so I create 2 servers on each and 2 clients, on the application A the server is running on port 1287 and on application B on port 10001, the problem is that the client of application A is loosing the connection, but on the log of the server on application B is sending the correct response, I keep getting an IOException and I can't find why, however when I am debugging, step by step the connection works fine and the apps work fine together, but if I left them run on their own I keep getting the error screens I create for this cases, this is the message I got on application A:
DEBUG || TcpWrapperServer || Socket closed...
DEBUG || TcpClient || Enviando solicitud(110.152.100.117:10001):{WEBCLOCK|SHIFT|0002149}
DEBUG || TcpClient || try/catch
DEBUG || TcpClient || Connecting... 110.152.100.117:10001
DEBUG || TcpClient || getStream()...
DEBUG || TcpClient || preparing to read stream...
DEBUG || TcpClient ||
WARNING data not available...
ERROR || TcpClient || IOException: Unable to read data from the transport connection.
ERROR || TcpClient || IOException(InnerExc): System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host at System.Net.Sockets.Socket.ReceiveNoCheck(Byte[] buffer, Int32 index, Int32 request, SocketFlags socketFlags)
ERROR || TcpClient || IOException(traace): at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) at System.IO.StreamReader.ReadBuffer(Char[] userBuffer, Int32 userOffset, Int32 desiredChars, Boolean& readToUserBuffer) at System.IO.StreamReader.Read(Char[] buffer, Int32 index, Int32 count)
at pvc_20.pvcTcpClient.sendRequest(String msg) at pvc_20.BarcodeSession.proccessPartnerID(String partnerid)
this is the log on server on app B:
INFO || TcpServerWrapper || ProcessClient ||
DEBUG ||TcpWrapperServer || processCommand || msg:{WEBCLOCK|SHIFT|0001371}
DEBUG || TcpWrapperServer || processCommand || response:{WEBCLOCK|SHIFT|ONPROCESS}
also this is the log that I get when I debug:
DEBUG || TcpClient || Enviando
solicitud(110.152.100.117:10001):{WEBCLOCK|SHIFT|0001371}
DEBUG || TcpClient || try/catch 1/1/2000
DEBUG || TcpClient || Connecting...110.152.100.117:10001
DEBUG || TcpClient || getStream()...
DEBUG || TcpClient || reading stream...
DEBUG || TcpClient || respuesta recibida:{WEBCLOCK|SHIFT|ONPROCESS}
this is the client part on application A:
public TcpClient() {
m_server = Settings.ServerIP;
m_tcpPort = Settings.TcpPort;
m_hasReponse = false;
m_response = String.Empty;
m_buffer = null;
}
public TcpClient( String server , int tcpPort)
{
m_server = server;
m_tcpPort = tcpPort;
m_hasReponse = false;
m_response = String.Empty;
m_buffer = null;
}
public void sendRequest(String msg)
{
Log.debug("TcpClient", "sending to (" + m_server + ":" + m_tcpPort+"):"+ msg);
string m_currentIP = Utils.LocalIPAddress();
m_clientSocket = null;
m_hasReponse = false;
m_response = String.Empty;
Log.debug("TcpClient", "try/catch");
try
{
m_clientSocket = new TcpClient();
Log.debug("TcpClient", "Connecting... "+m_server+":"+ m_tcpPort);
m_clientSocket.Connect(
new IPEndPoint(
IPAddress.Parse(m_server),
m_tcpPort) );
Log.debug("TcpClient", "getStream()...");
m_stream = m_clientSocket.GetStream();
byte[] outstream = System.Text.Encoding.ASCII.GetBytes(msg);
m_stream.Write(outstream, 0, outstream.Length);
m_stream.Flush();
StreamReader streamReader = new StreamReader(m_stream);
if (m_stream.CanRead)
{
Log.debug("TcpClient", "preparing to read stream...");
StringBuilder res = new StringBuilder();
byte[] inStream = new byte[1024];
int bytesread = 0;
int index = 0;
char[] bfrRes = new char[1024];
if (!m_stream.DataAvailable)
{
Log.debug("TcpClient", "warning data not available...");
}
/* while (bytesread != 125)
{
bytesread = m_stream.ReadByte();
Log.debug("TcpClient", "reading byte: " + bytesread);
char c;
try
{
c = Convert.ToChar(bytesread); }
catch
{
c = ' ';
}
res.Append(c);
index++;
}*/
streamReader.Read(bfrRes, 0, 1024);
// m_response = res.ToString();
m_response = new string(bfrRes);
Log.debug("TcpClient", "response:" + m_response);
}
if (m_response.Length > 0)
m_hasReponse = true;
else
m_hasReponse = false;
}
catch (SocketException e)
{
Log.error("TcpClient", "SocketException: "+e.Message);
m_hasReponse= false;
m_response = String.Empty;
}catch(WebException we){
Log.error("TcpClient", "Webxception: " + we.Message);
Log.error("TcpClient", "WebException(InnerExc): " + we.InnerException);
Log.error("TcpClient", "WebException(traace): " + we.StackTrace);
m_hasReponse = false;
m_response = String.Empty;
}
catch (IOException ioe)
{
Log.error("TcpClient", "IOException: " + ioe.Message);
Log.error("TcpClient", "IOException(InnerExc): " + ioe.InnerException);
Log.error("TcpClient", "IOException(trace): " + ioe.StackTrace);
m_hasReponse = false;
m_response = String.Empty;
}
catch (Exception e)
{
Log.error("TcpClient","Exception:"+ e.Message);
m_hasReponse = false;
m_response = String.Empty;
}
finally
{
if (null != m_stream)
m_stream.Close();
m_clientSocket.Close();
}
return ;
}
public String response
{
get { return m_response; }
}
public bool hasResponse {
get { return m_hasReponse; }
}
public byte[] buffer {
get { return m_buffer; }
}
this is the server wraper side on application B:
class TcpServerWrapper
{
TcpClient m_client;
WebClock m_main;
bool isValidCommand = false;
public TcpServerWrapper(TcpClient client, WebClock m)
{
Log.debug("TcpServerWrapper", "init");
m_client = client;
m_main = m;
}
public void ProcessClient()
{
String remoteIP = ((IPEndPoint)m_client.Client.RemoteEndPoint).Address.ToString();
Log.info("TcpServerWrapper", " ProcessClient || Processing from:" + remoteIP);
NetworkStream clientStream = m_client.GetStream();
byte[] message = new byte[2048];
int bytesRead;
bytesRead = 0;
try
{
//blocks until a client sends a message
int i = 0;
int b = 0;
while (b != 125)
{
b = clientStream.ReadByte();
message[i] = (byte)b;
i++;
}
bytesRead = message.Length;
}
catch (Exception e)
{
//a socket error has occured
Log.error("TcpWrapperServer", "ProcessClient || Can't read client petition || ex:" + e.Message);
bytesRead = 0;
//break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
Log.warning("TcpWrapperServer", "ProcessClient || Client disconected ");
//break;
}
else
{
//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
String req = encoder.GetString(message, 0, bytesRead);
String res = processCommand(req);
NetworkStream stream = m_client.GetStream();
byte[] buffer = encoder.GetBytes(res);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
clientStream.Close();
m_client.Close();
if (isValidCommand)
{
m_main.wakeApp("");
}
Log.debug("TcpWrapperServer", "ProcessClient || Socket closed");
}
private String processCommand(String msg)
{
Log.debug("TcpWrapperServer", "processCommand || msg:" + msg);
String response = "";
msg = msg.Replace(" ", String.Empty);
msg = msg.ToUpper();
if (!msg.StartsWith("{") || !msg.EndsWith("}"))
{
return "{WEBCLOCK| RESULT=ERROR|MESSAGE=El mensaje no es un comando valido de la aplicacion.}";
}
msg = msg.Replace("{", "");
msg = msg.Replace("}", "");
String[] commands = msg.Split('|');
//{WEBCLOCK|SHIFT|0001371}
if (commands[0] == "WEBCLOCK")
{
if (commands[1] == "SHIFT")
{
string socioid = commands[2];
if (socioid.Length == 7)
{
Settings.TMP_ScannedPartnerId = socioid;
isValidCommand = true;
response = "{WEBCLOCK|SHIFT|ONPROCESS}\n";
}
else
{
response = "{WEBCLOCK| RESULT=ERROR|MESSAGE=El mensaje no es un comando valido de la aplicacion.}";
}
}
else {
response = "{WEBCLOCK| RESULT=ERROR|MESSAGE=El mensaje no es un comando valido de la aplicacion.}";
}
}else
{
response = "{WEBCLOCK| RESULT=ERROR|MESSAGE=El mensaje no es un comando valido para WEBCLOCK}";
}
Log.debug("TcpWrapperServer", "processCommand || response:" + response);
return response;
}
}
I really don't see why the local server on Application B is being closed.
Have you verified you're not hitting the ReceiveTimeout?
Related
i created a proxy server in c# to replace my file on local
for example :
i get http header with HttpListener and parse it to take file url and then i build a fake Response to download the file from my local , but is it possible to do that with HTTPS too ?
i tried to do it but i get only CONNECT request type.
if is it possible , how can i do this ?
url is like this : https://sgst.prod.dl.playstation.net/sgst/prod/00/PPSA01876_00/app/info/62/f_c2855f23a9de280972d5dc1c1fae07240bb76193a65393a6e304588ffb111b8a/UP0001-PPSA01876_00-FARCRY6GAME00000.crc
and in fiddler :
This is Tunnel with CONNECT request type
and what i want to get is :
This is HTTPS GET request type with URL that i need
so this is my code but i get host only (Host: sgst.prod.dl.playstation.net)
private void QueryHandle(string query)
{
HeaderFields = ParseQuery(query);
if ((HeaderFields == null) || !HeaderFields.ContainsKey("Host"))
SendBadRequest();
else
{
int num;
string requestedPath;
int index;
if (HttpRequestType.ToUpper().Equals("CONNECT"))
{
index = RequestedPath.IndexOf(":");
if (index >= 0)
{
requestedPath = RequestedPath.Substring(0, index);
num = RequestedPath.Length > (index + 1) ? int.Parse(RequestedPath.Substring(index + 1)) : 443;
}
else
{
requestedPath = RequestedPath;
num = 80;
}
}
else
{
index = HeaderFields["Host"].IndexOf(":");
if (index > 0)
{
requestedPath = HeaderFields["Host"].Substring(0, index);
num = int.Parse(HeaderFields["Host"].Substring(index + 1));
}
else
{
requestedPath = HeaderFields["Host"];
num = 80;
}
if (HttpRequestType.ToUpper().Equals("POST"))
{
int tempnum = query.IndexOf("\r\n\r\n");
_mHttpPost = query.Substring(tempnum + 4);
}
}
var localFile = String.Empty;
if (MonitorLog.RegexUrl(RequestedUrl))
localFile = UrlOperate.MatchFile(RequestedUrl);
_uinfo.PsnUrl = string.IsNullOrEmpty(_uinfo.PsnUrl) ? RequestedUrl : _uinfo.PsnUrl;
if (!HttpRequestType.ToUpper().Equals("CONNECT") && localFile != string.Empty && File.Exists(localFile))
{
_uinfo.ReplacePath = localFile;
_updataUrlLog(_uinfo);
SendLocalFile(localFile, HeaderFields.ContainsKey("Range") ? HeaderFields["Range"] : null, HeaderFields.ContainsKey("Proxy-Connection") ? HeaderFields["Proxy-Connection"] : null);
}
if (HttpRequestType.ToUpper().Equals("CONNECT"))
{
IPHostEntry hostEntry;
hostEntry = Dns.GetHostEntry(requestedPath);
string server = hostEntry.AddressList[0].ToString();
IPAddress hostIp = IPAddress.Parse(server);
var remoteEp = new IPEndPoint(hostIp, num);
DestinationSocket = new Socket(remoteEp.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
DestinationSocket.BeginConnect(remoteEp, OnConnected, DestinationSocket);
_uinfo.Host = hostEntry.AddressList[0].ToString();
_uinfo.ReplacePath = string.Empty;
_updataUrlLog(_uinfo);
}
private void OnConnected(IAsyncResult ar)
{
try
{
if (DestinationSocket == null)
{
return;
}
string str;
DestinationSocket.EndConnect(ar);
if (HttpRequestType.ToUpper().Equals("CONNECT"))
{
if (ClientSocket != null)
{
str = HttpVersion + " 200 Connection Established\r\n\r\n";
ClientSocket.BeginSend(Encoding.ASCII.GetBytes(str), 0, str.Length, SocketFlags.Partial,
OnOkSent, ClientSocket);
}
}
else
{
str = RebuildQuery();
DestinationSocket.BeginSend(Encoding.ASCII.GetBytes(str), 0, str.Length, SocketFlags.None,
OnQuerySent, DestinationSocket);
}
}
catch
{
Dispose();
}
}
private void OnOkSent(IAsyncResult ar)
{
try
{
if (ClientSocket != null && ClientSocket.EndSend(ar) == -1)
{
Dispose();
}
else
{
StartRelay();
}
}
catch
{
Dispose();
}
}
so i am not familiar with socket , ssl , protocols ...
i will thank you for your help and sorry for my bad english
I am having problems updating a ListView on C# WinForm. The application is a test harness which connects to a TCP Server and receives a data stream. The test harness will then be used to create multiple connections to the server to do load testing. Each task is started using the following command where the number of task is entered on the form:
for (int i = 0; i < noTasks; i++)
{
bool saveAudio = noTasksCheckedListBox.GetItemCheckState(i) == CheckState.Checked; // true : false;
taskArray[i] = Task.Run(() => SendMessage((initId + i).ToString(), saveAudio, audioServerIP));
}
The SendMessage function creates the TCP client connection and creates a AsyncCallBack to process the incoming stream.
void SendMessage(string id, bool saveWav, string serverIP)
{
TcpClient tcpclientAudio = new TcpClient();
string message = "GET /msg?id=" + id + "&type=0 HTTP/1.1\r\n";
NetworkObject audioObj = new NetworkObject
{
tcp = tcpclientAudio,
ConnectionType = FileType.Audio,
URL = message
};
if (saveWav)
{
tcpclientAudio.BeginConnect(IPAddress.Parse(serverIP), 8008, new AsyncCallback(CallBackConnectMethod01), audioObj);
}
else
{
tcpclientAudio.BeginConnect(IPAddress.Parse(serverIP), 8008, new AsyncCallback(CallBackConnectMethod02), audioObj);
}
}
The only difference between the CallBackConnctMethod is that 02 save the data to a file.
void CallBackConnectMethod02(IAsyncResult result)
{
NetworkObject obj = (NetworkObject)result.AsyncState;
TcpClient tcp = obj.tcp;
NetworkStream ns = tcp.GetStream();
startedProcessCount++;
int thisTask = startedProcessCount;
byte[] buffer = new byte[2048];
string message = obj.URL;
byte[] request = Encoding.ASCII.GetBytes(message);
ns.Write(request, 0, request.Length);
ns.Read(buffer, 0, 1000);
RefreshTable(thisTask, "Incoming", null);
......
}
When debugging the app goes to the RefreshTable function a disappears when it goes in to the delegate section.
private void RefreshTable(int taskNo, string status, string misc)
{
if (this.tasksListView.InvokeRequired)
{
this.Invoke((MethodInvoker) delegate {
DateTime nowDateTime = DateTime.Now;
string now = nowDateTime.Year.ToString("D4") + nowDateTime.Month.ToString("D2") + nowDateTime.Day.ToString("D2") + "-" + nowDateTime.Hour.ToString("D2") + nowDateTime.Minute.ToString("D2") + nowDateTime.Second.ToString("D2");
string taskId = "Task-" + taskNo.ToString("D3");
if (status == "Incoming")
{
ListViewItem taskLVI = tasksListView.Items.Add(taskId);
taskLVI.SubItems.Add(now);
taskLVI.SubItems.Add(" ");
taskLVI.SubItems.Add(" ");
if (string.IsNullOrEmpty(misc))
taskLVI.SubItems.Add(" ");
else
taskLVI.SubItems.Add(misc);
taskLVI.SubItems.Add(" ");
}
else
{
switch (status)
{
case "Lost":
case "Completed":
case "Exception":
ListViewItem listViewItem = null;
for (int i = 0; i < tasksListView.Items.Count; i++)
{
if (tasksListView.Items[i].SubItems[0].Text == taskId)
{
listViewItem = tasksListView.Items[i];
break;
}
}
if (listViewItem != null)
ToListViewItem(listViewItem, status, misc, now);
break;
default:
break;
}
}
tasksListView.Refresh();
});
}
}
I tried to poll the device using the Modbus protocol for TCP/IP, and it works well, but there are problems.
If I run this code on a weak computer, the response time will increase and very much...
The difference in polling speed is about 6 seconds.
For example - I send a request on my computer 01 03 04 50 00 01 85 2B and received a response in 0.057 seconds, and on a weaker computer this request is received in 0.560 seconds. The answer is the same 01 03 02 02 C1 78 B4. The device is the same and connected in the same way.
public override void Run()
{
IsRunning = true;
OnJobStarted?.Invoke(this);
OnLogMessage?.Invoke(this, "JOB START");
try
{
while (Job.ThreadState == ThreadState.Running && !isJobTerminated)
{
var ts = DateTime.Now;
if (!Ping())
{
}
var es = DateTime.Now;
var ms = (es - ts).TotalMilliseconds;
while (!isJobTerminated && (DateTime.Now - ts).TotalMilliseconds <= this.PingInterval * 1000)
Thread.Sleep(10);
}
}
catch (Exception ex)
{
OnLogMessage?.Invoke(this, " RUN: " + ex.Message);
}
OnLogMessage?.Invoke(this, "JOB END");
OnJobEnded?.Invoke(this);
IsRunning = false;
}
.
public override bool Ping()
{
var result = false;
try
{
PingStat.LastPingDateTime = DateTime.Now;
PingStat.PingInterval = this.PingInterval;
result = true;
PingStat.TotalPingCount++;
if (!result)
PingStat.ErrorCount++;
if (result)
{
foreach (var md in Children.Where(m => !m.IsSuspended && m.IsEnabled))
{
var pingResult = ReadConfiguration(md).ErrorCode == 0;
Thread.Sleep(10);
if (pingResult)
ReadState(md);
if (pingResult && md.IsMaskChanged)
{
var maskResult = WriteSingleRegister(md, 0x05FC, md.Mask);
md.IsMaskChanged = !(maskResult.ErrorCode == 0);
}
md.PingStat.IsLastPingOk = pingResult;
md.OnPing?.Invoke(md, pingResult);
}
}
}
catch (Exception ex)
{
OnLogMessage?.Invoke(this, ex.Message + Environment.NewLine + ex.StackTrace);
result = false;
}
finally
{
PingStat.IsLastPingOk = result;
OnPing?.Invoke(this, result);
}
return result;
}
.
public override RcResult ExecuteModBus(RcModBusDevice device, byte[] request, out byte[] answer)
{
answer = null;
var result = new RcResult();
var dt = DateTime.Now;
Random rnd = new Random();
try
{
OnLogMessage?.Invoke(this, "ExecuteModBus Lock?");
lock (communication)
{
OnLogMessage?.Invoke(this, "ExecuteModBus Lock!");
using (var tcpClient = new TcpClient())
{
tcpClient.Connect(IP, Port);
tcpClient.SendTimeout = SendTimeout;
tcpClient.ReceiveTimeout = Math.Max(100, ReceiveTimeout);
using (var stream = tcpClient.GetStream())
{
dt = DateTime.Now;
OnLogMessage?.Invoke(this, "REQUEST->:" + Utils.BytesToHex(request));
stream.Write(request, 0, request.Length);
var tmp = new byte[0xA0];
int dataLength = 0;
try
{
for (dataLength = 0; dataLength < tmp.Length; dataLength++)
{
tmp[dataLength] = (byte)(stream.ReadByte());
tcpClient.ReceiveTimeout = 100 - Properties.Settings.Default.coefIP;
Thread.Sleep(0);
}
}
catch (Exception ex)
{
}
if (dataLength < 2)
result.ErrorCode = 1;
else
{
var crc = Utils.GetCRC(tmp, 0, dataLength - 2);
if (crc[0] != tmp[dataLength - 2] || crc[1] != tmp[dataLength - 1])
{
result.ErrorCode = 1;
result.ErrorText = "Bad CRC";
}
}
answer = new byte[dataLength];
Array.Copy(tmp, 0, answer, 0, dataLength);
}
OnLogMessage?.Invoke(this, "ANSWER<-:" + Utils.BytesToHex(answer));
if (device != null)
SaveToLog(DbID, device.DbID, dt, Utils.BytesToHex(request), DateTime.Now, Utils.BytesToHex(answer));
}
}
OnLogMessage?.Invoke(this, "ExecuteModBus UnLock");
}
catch (Exception ex)
{
SaveToLog(DbID, device.DbID, dt, Utils.BytesToHex(request), DateTime.Now, "ERROR", ex.Message);
OnLogMessage?.Invoke(this, ex.Message + Environment.NewLine + ex.StackTrace);
result = new RcResult() { ErrorCode = 1, ErrorText = ex.Message };
}
return result;
}
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")?
For load testing purposes I need to simulate multiple users trying to login to a system at the same time. I have code written by another developer that can send a login request to the system. With an ok login it will also return other information in xml.
I've tried using Parallel.ForEach, but dont have any real experience with parallel programming:
Parallel.ForEach(clientList, client =>
{
RunTest(client);
});
public void RunTest(object data)
{
if (!(data is IGprsClient))
{
return;
}
_noRunningTests += 1;
IGprsClient gprsClient = data as IGprsClient;
DateTime startTime = DateTime.Now;
Log(gprsClient.Id, "Test started.");
bool result = gprsClient.StartTest(20000);
DateTime endTime = DateTime.Now;
TimeSpan diff = endTime - startTime;
if (result == false)
{
Log(gprsClient.Id, "Test failed.");
}
Log(gprsClient.Id, "Test took {0}ms. ", (int)diff.TotalMilliseconds);
_noRunningTests -= 1;
}
override public bool StartTest(int timeout)
{
_testStarted = true;
try
{
LogDebug("Trying to connect.");
_client = new TcpClient(ipAddress, port);
LogDebug("Connected.");
bool result = false;
//Todo: insert testcase into client
switch (TestCaseName)
{
case "LoginTEST":
var testCase = new LoginTEST(this);
result = testCase.Execute(user, pwd, phoneNum);
break;
default:
Log("Unknown test case: " + TestCaseName);
break;
}
_client.Close();
return result;
}
catch (Exception ex)
{
if (_client != null)
_client.Close();
Log(ex.Message);
return false;
}
}
Which in turn will send the request and read the response.
public bool Execute(string user, string pwd, string phoneNum)
{
SendDataListRequest(userId);
string requiredDataResponse = Client.ReadMsg();
return true;
}
Run test will send a request and reads the message like so:
public string ReadMsg()
{
int msgLength = -1;
var stream = _client.GetStream();
while (_testStarted)
{
int b = stream.ReadByte();
if (b == -1)
{
return "";
}
else if (b == 0x02 || msgLength == -1)
{
while (b != 0x02 && _testStarted)
{
b = stream.ReadByte(); // Finds the start token
if (b == -1)
{
return "";
}
}
msgLength = 0; // Starts collecting data
}
else if (b == 0x03)
{
byte[] encryptedMsg = Convert.FromBase64String(
Encoding.UTF8.GetString(byteBuffer, 0, msgLength));
byte[] decryptedMsg = SttCipher.DecryptMessage(encryptedMsg);
MemoryStream ms = new MemoryStream(decryptedMsg);
GZipStream gZipStream = new GZipStream(ms, CompressionMode.Decompress, true);
var bufLen = ReadAllBytesFromStream(gZipStream, decompressedBuffer);
gZipStream.Close();
string completeMsg = Encoding.UTF8.GetString(decompressedBuffer, 0, bufLen);
if (completeMsg.Length < 500)
LogDebug("Received XML-data:\n{0}", completeMsg);
else
LogDebug("Received XML-data: {0} bytes\n{1}...", completeMsg.Length, completeMsg.Substring(0, 500));
return completeMsg;
}
else
{
if (byteBuffer.Length <= msgLength)
{
throw new Exception("XML message too long!");
}
byteBuffer[msgLength] = (byte)b;
msgLength++;
}
}
return "";
}
Running one client is fine and will wait for the response. The issue is with several clients, the responses gets cut off. Leaving me with unclosed xml in the response.But I cant't figure out why. Does anyone have a reasonable explanation and/or a solution or a better way of doing it?