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;
}
Related
I wrote a bot in C#, I used Selenium.
Problem: When I start more threads at same time, the bot does the work in the first window. All of the e-mail addresses are being added to the "E-mail" textbox in the same window instead of one e-mail address per window.
But it should look like:
Start function: DivisionStart()
private void DivisionStart() {
foreach(var account in BotConfig.AccountList) {
while (CurrentBotThreads >= BotConfig.MaxLoginsAtSameTime) {
Thread.Sleep(1000);
}
StartedBotThreads++;
CurrentBotThreads++;
int startIndex = (StartedBotThreads * BotConfig.AdsPerAccount + 1) - BotConfig.AdsPerAccount - 1;
int stopIndex = BotConfig.AdsPerAccount * CurrentBotThreads;
if (stopIndex > BotConfig.ProductList.Count) {
stopIndex = BotConfig.ProductList.Count;
}
Debug.Print("Thread: " + StartedBotThreads);
var adList = GetAdListBy(startIndex, stopIndex);
foreach(var ad in adList) {
Debug.Print("Für thread: " + StartedBotThreads + " | Anzeige: " + ad.AdTitle);
}
Debug.Print("Parallel");
var ebayBotThread = new Thread(() => {
var botOptions = new IBotOptionsModel() {
CaptchaSolverApiKey = CaptchaSolverApiKey,
ReCaptchaSiteKey = "6LcZlE0UAAAAAFQKM6e6WA2XynMyr6WFd5z1l1Nr",
StartPageUrl = "https://www.ebay-kleinanzeigen.de/m-einloggen.html?targetUrl=/",
EbayLoginEmail = account.AccountEmail,
EbayLoginPassword = account.AccountPassword,
Ads = adList,
};
var ebayBot = new EbayBot(this, botOptions);
ebayBot.Start(StartedBotThreads);
Thread.Sleep(5000);
});
ebayBotThread.Start();
}
}
The class with function which will be executed in each thread:
using OpenQA.Selenium;
using Selenium.WebDriver.UndetectedChromeDriver;
using System.Diagnostics;
using TwoCaptcha.Captcha;
using System.Drawing;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Chrome.ChromeDriverExtensions;
namespace EbayBot
{
class EbayBot
{
public Selenium.Extensions.SlDriver Driver;
private WebDriverHelper DriverHelper;
private Bot Sender;
private bool CaptchaSolved = false;
public IBotOptionsModel Options;
public EbayBot(Bot sender, IBotOptionsModel options)
{
Sender = sender;
Options = options;
}
public void Start(int threadIndex)
{
var chromeOptions = new ChromeOptions();
/*if (Sender.BotConfig.EnableProxy)
{
chromeOptions.AddHttpProxy(
Options.Proxy.IpAddress,
Options.Proxy.Port,
Options.Proxy.Username,
Options.Proxy.Password
);
}*/
Driver = UndetectedChromeDriver.Instance(null, chromeOptions);
DriverHelper = new WebDriverHelper(Driver);
string status = "";
Debug.Print("Bot-Thread: " + threadIndex);
Driver.Url = Options.StartPageUrl + Options.EbayLoginEmail;
PressAcceptCookiesButton();
Login();
if (!CaptchaSolved) return;
Driver.Wait(3);
if (LoginError() || !IsLoggedIn())
{
status = "Login für '" + Options.EbayLoginEmail + "' fehlgeschlagen!";
Debug.Print(status);
Sender.ProcessStatus = new IStatusModel(status, Color.Red);
return;
}
else
{
status = "Login für '" + Options.EbayLoginEmail + "' war erfolgreich!";
Debug.Print(status);
Sender.ProcessStatus = new IStatusModel(status, Color.Green);
}
Driver.Wait(5);
BeginFillFormular();
}
private bool CookiesAccepted()
{
try
{
var btnAcceptCookies = Driver.FindElement(By.Id(Config.PageElements["id_banner"]));
return btnAcceptCookies == null;
}
catch (Exception)
{
return true;
}
}
private void PressAcceptCookiesButton()
{
DriverHelper.WaitForElement(Config.PageElements["id_banner"], "", 10);
if (CookiesAccepted()) return;
var btnAcceptCookies = Driver.FindElement(By.Id(Config.PageElements["id_banner"]));
btnAcceptCookies.Click();
}
private bool IsLoggedIn()
{
Debug.Print("Check if logged in already");
try
{
var userEmail = Driver.FindElement(By.Id("user-email")).Text;
return userEmail.ToLower().Contains(Options.EbayLoginEmail);
}
catch (Exception)
{
return false;
}
}
private bool LoginError()
{
try
{
var loginErrorH1 = Driver.FindElements(By.TagName("h1"));
return loginErrorH1[0].Text.Contains("ungültig");
}
catch (Exception)
{
return false;
}
}
private void Login()
{
if (IsLoggedIn()) return;
string status = "Anmelden bei " + Options.EbayLoginEmail + "...";
Debug.Print(status);
Sender.ProcessStatus = Sender.ProcessStatus = new IStatusModel(status, Color.DimGray);
Driver.Wait(5);
var fieldEmail = Driver.FindElement(By.Id(Config.PageElements["id_login_email"]));
var fieldPassword = Driver.FindElement(By.Id(Config.PageElements["id_login_password"]));
var btnLoginSubmit = Driver.FindElement(By.Id(Config.PageElements["id_login_button"]));
fieldEmail.SendKeys(Options.EbayLoginEmail);
Driver.Wait(4);
fieldPassword.SendKeys(Options.EbayLoginPassword);
SolveCaptcha();
if (!CaptchaSolved)
{
return;
}
Debug.Print("Clicking login button");
btnLoginSubmit.Click();
}
public void BeginFillFormular()
{
Debug.Print("Formular setup, Inserate: " + Options.Ads.Count);
foreach (var adData in Options.Ads)
{
Debug.Print("Setting up formular for " + adData.AdTitle);
var adFormular = new AdFormular(Driver, adData, Options);
adFormular._EbayBot = this;
adFormular.CreateAd(Sender);
// 10 seconds
Debug.Print("Nächstes Insert für " + adData.AdTitle);
}
}
public string GetSolvedCaptchaAnswer(string captchaUrl = "")
{
string code = string.Empty;
var solver = new TwoCaptcha.TwoCaptcha(Options.CaptchaSolverApiKey);
var captcha = new ReCaptcha();
captcha.SetSiteKey(Options.ReCaptchaSiteKey);
captcha.SetUrl(captchaUrl == "" ? Options.StartPageUrl : captchaUrl);
try
{
solver.Solve(captcha).Wait();
code = captcha.Code;
}
catch (AggregateException e)
{
Sender.ProcessStatus = new IStatusModel("Captcha Api-Fehler: " + e.InnerExceptions.First().Message, Color.Red);
Driver.Wait(10);
}
return code;
}
public void SolveCaptcha(string captchaUrl = "")
{
Debug.Print("Solving captcha...");
var solvedCaptchaAnswer = GetSolvedCaptchaAnswer(captchaUrl);
if (solvedCaptchaAnswer == string.Empty)
{
Debug.Print("Captcha konnte nicht gelöst werden");
Sender.ProcessStatus = new IStatusModel("Captcha konnte nicht gelöst werden", Color.Red);
CaptchaSolved = false;
Driver.Wait(10);
return;
}
CaptchaSolved = true;
Debug.Print("Captcha answer: " + solvedCaptchaAnswer);
Driver.ExecuteScript("document.getElementById('g-recaptcha-response').innerHTML = '" + solvedCaptchaAnswer + "'");
Debug.Print("Captcha solved!");
Driver.Wait(2);
}
}
}
If I remove the Thread.Sleep(5000); in the DivisionStart function it will work, but I need it I actually want to wait for a found proxy but I simulated it with Thread.Sleep
How can I solve my problem?
Thanks for any answer!
I fixed it.
I used UndetectedChromeDriver wich does not use different ports.
I use another Undetected driver now.
Thank you all
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")?
I am trying to create a windows service that calls a thread in a library. This is all in c#. The library has a function that reads from an oracle database, processes the data, stores it in a SQL Server database and updates the records in the oracle database. I run tests on this and saw that the loop runs about 80,000 times and then without throwing any errors (i even checked the event log) nothing happens. Please help with this
This is the code
Windows Service
protected override void OnStart(string[] args)
{
try
{
base.OnStart(args);
controller = new BillingController();
thread = new Thread(new ThreadStart(controller.dowork));
thread.Start();
AppLogs.LogtoFile("SmartCDRBillingService.log", string.Format("SmartCDRBillingService started successfully"));
}
catch (Exception ex)
{
AppLogs.LogtoFile("SmartCDRBillingService.log", string.Format("Start Service error: {0}: {1}:", ex.Message.ToString(), ex.InnerException));
}
}
Controller
public BillingController()
{
AppConfig.LoadSettings();
}
public void dowork()
{
try
{
BillingQueue nLogic = new BillingQueue();
nLogic.QueueWorkItems();
}
catch (Exception ex)
{
//log
AppLogs.LogtoFile("BillingController.log", string.Format("dowork error: {0}: {1}:", ex.Message.ToString(), ex.InnerException));
}
}
Queue
public void QueueWorkItems()
{
new System.Threading.Thread(new System.Threading.ThreadStart(doQueueWork)).Start();
}
private void doQueueWork()
{
counter = 1;
while (true)
{
counter++;
List<EventUsageObject> eList = new List<EventUsageObject>();
try
{
eList = _osqlcon.getallusageevents();
if (eList.Count == 0)
{
continue;
}
else
{
ProcessUsageRequest(eList);//for Event Usage
}
}
catch (Exception ex)
{
//log the error
AppLogs.LogtoFile("BillingQueue.log", string.Format("doQueueWork error: {0}: {1}:", ex.Message.ToString(), ex.InnerException));
}
}
}
public List<EventUsageObject> getallusageevents()
{
List<EventUsageObject> recobjec = new List<EventUsageObject>();
OracleConnection conn = new OracleConnection();
try
{
conn.ConnectionString = osql.getOracleConnectionString();
conn.Open();
OracleCommand command = conn.CreateCommand();
command.CommandType = CommandType.StoredProcedure;
string query = "SMART_DWH_OBJECT.GETALLEVENTSUSAGE";
command.CommandText = query;
OracleParameter myParameter = new OracleParameter("rc", OracleDbType.RefCursor);
command.Parameters.Add("OUT_DATA", OracleDbType.RefCursor).Direction = ParameterDirection.Output;
using (OracleDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection))
{
reader.FetchSize = 10000;
while (reader.Read())
{
try
{
EventUsageObject info = new EventUsageObject();
info.CallStart = Convert.ToDateTime(reader["E_TIME"].ToString());
info.CallingMsisdn = reader["ACC_NBR"].ToString();
info.CalledMsisdn = reader["CALLED_MSISDN"].ToString();
info.Re_Id = Convert.ToInt32(reader["RE_ID"].ToString());
info.EventName = reader["EVENT_NAME"].ToString();
info.Duration = Convert.ToInt32(reader["DURATION"].ToString());
info.Duration2 = Convert.ToInt32(reader["DURATION2"].ToString());
info.Duration3 = Convert.ToInt32(reader["DURATION3"].ToString());
info.Duration4 = Convert.ToInt32(reader["DURATION4"].ToString());
info.Uplink = Convert.ToInt32(reader["UPLINK"].ToString());
info.Downlink = Convert.ToInt32(reader["DOWNLINK"].ToString());
info.PriceList = reader["PRICE_LIST"].ToString();
info.Cell_A = reader["CELL_A"].ToString();
info.Cell_B = reader["CELL_B"].ToString();
info.Acct_item_Type_Id1 = Convert.ToInt32(reader["ACCT_ITEM_TYPE_ID1"].ToString());
info.Acct_item_Type_Id2 = Convert.ToInt32(reader["ACCT_ITEM_TYPE_ID2"].ToString());
info.Acct_item_Type_Id3 = Convert.ToInt32(reader["ACCT_ITEM_TYPE_ID3"].ToString());
info.Acct_item_Type_Id4 = Convert.ToInt32(reader["ACCT_ITEM_TYPE_ID4"].ToString());
info.BalanceType1 = reader["BALANCE_TYPE1"].ToString();
info.BalanceType2 = reader["BALANCE_TYPE2"].ToString();
info.BalanceType3 = reader["BALANCE_TYPE3"].ToString();
info.BalanceType4 = reader["BALANCE_TYPE4"].ToString();
string d1 = reader["CHARGE1"].ToString();
string d2 = reader["CHARGE2"].ToString();
string d3 = reader["CHARGE3"].ToString();
string d4 = reader["CHARGE4"].ToString();
info.Charge1 = Convert.ToInt32(reader["CHARGE1"].ToString());
info.Charge2 = Convert.ToInt32(reader["CHARGE2"].ToString());
info.Charge3 = Convert.ToInt32(reader["CHARGE3"].ToString());
info.Charge4 = Convert.ToInt32(reader["CHARGE4"].ToString());
info.Prebalance1 = Convert.ToDouble(reader["PRE_BALANCE1"].ToString());
info.Prebalance2 = Convert.ToDouble(reader["PRE_BALANCE2"].ToString());
info.Prebalance3 = Convert.ToDouble(reader["PRE_BALANCE3"].ToString());
info.Prebalance4 = Convert.ToDouble(reader["PRE_BALANCE4"].ToString());
info.Recstatus = 0;
recobjec.Add(info);
}
catch (Exception ex)
{
continue;
}
}
}
conn.Close();
conn.Dispose();
}
catch (Exception ex)
{
AppLogs.LogtoFile("DBAPIError.log", string.Format("DBAPI error on getallusageevents error: {0}: {1}:", ex.Message.ToString(), ex.StackTrace));
}
return recobjec;
}
public void ProcessUsageRequest(List<EventUsageObject> list)
{
try
{
//log the eventusage into the database.
if (list.Count == 0)
//do nothing
return;
else
_mssqlcon.logEventUsage(list, _osqlcon);
}
catch (Exception ex)
{
AppLogs.LogtoFile("BillingQueue.log", string.Format("ProcessUsageRequest error on loggingeventusage: {0}: {1}:", ex.Message.ToString(), ex.InnerException));
}
}
public void logEventUsage(List<EventUsageObject> ilist, DBAPI osql)
{
int counter = 0;
try
{
foreach (EventUsageObject log in ilist)
{
try
{
counter++;
sql.executeNonQueryStoredProcedure("dbo.sp_dwh_eventusage", log.CallStart.ToString(), log.CallingMsisdn, log.CalledMsisdn, log.Re_Id.ToString(),
log.EventName.ToString(), log.Duration.ToString(), log.Duration2.ToString(), log.Duration3.ToString(),
log.Duration4.ToString(), log.Uplink.ToString(), log.Downlink.ToString(), log.PriceList, log.Cell_A,
log.Cell_B, log.Acct_item_Type_Id1.ToString(), log.Acct_item_Type_Id2.ToString(), log.Acct_item_Type_Id3.ToString(),
log.Acct_item_Type_Id4.ToString(), log.BalanceType1, log.Charge1.ToString(), log.BalanceType2, log.Charge2.ToString(),
log.BalanceType3, log.Charge3.ToString(), log.BalanceType4, log.Charge4.ToString(), log.Recstatus.ToString(), log.Prebalance1.ToString(),
log.Prebalance2.ToString(), log.Prebalance3.ToString(), log.Prebalance4.ToString());
string query = "UPDATE dwh_ug_eventusage SET recstatus = 1" +
" WHERE E_TIME = TO_DATE('" + log.CallStart + "', 'MM/DD/YYYY HH:MI:SS PM') AND ACC_NBR = '" + log.CallingMsisdn + "'";
osql.executeNonQueryText(query);
AppLogs.LogtoFile("BillingQueue.log",
string.Format("ProcesssubscriptionRequest has processed: {0} record",
log.Msisdn));
}
catch (SqlException ex)
{
if (ex.Number == 2601)
{
string query = "UPDATE dwh_ug_eventusage SET recstatus = 1" +
" WHERE E_TIME = TO_DATE('" + log.CallStart + "', 'MM/DD/YYYY HH:MI:SS PM') AND ACC_NBR = '" + log.CallingMsisdn + "'";
osql.executeNonQueryText(query);
}
AppLogs.LogtoFile("DBAPIError.log", string.Format("DBAPI error on logEventUsage: {0}: {1}:",
continue;
}
}
}
catch (Exception ex)
{
AppLogs.LogtoFile("DBAPIError.log", string.Format("DBAPI error on logEventUsage: {0}: {1}:",
ex.Message.ToString(), ex.StackTrace));
}
}
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?
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?