C# Stopping TCP File Transfer - c#

I'm programming simple TCP file transfer using TcpListener on reciever side and TcpClient on sender side. I have 2 options - synchronnous or asynchronnous. If I use synchronnous, I have to put sending/recieving methods into BackgroundWorker, to prevent freezing GUI thread. Asynchronnous version is without problems...
My question is, how to stop running file transfer?
In synchronnous version I tried to use BackgroundWorker.CancelAsync() method, and in every loop iteration check BackgroundWorker.CancellationPending property, but it doesn't seems to work (CancelAsync is probably not setting CancellationPending property) :(
In asynchronnous version I tried to use volatile variable Indicator and in every Callback check its value. Problem is, when I change its value in Stop() method, and than I check it in Callback, callback still reads its previous value :(

CancelASync should work; did you set:
backgroundWorker.WorkerSupportsCancellation = true:

Are you saying that you aren't reading the correct "cancel state" when you check it? This suggests you're not synchronising the flag between your threads correctly.
Or is it just that you won't ever check for the "cancel state" unless you receive some new data? (From the way you describe your tx/rx "loops", in both sync and async cases you will have to receive a new datagram before you will get a chance to check the 'cancel' flag)
If you are in control of both ends of the data transfer, then whichever end (client or server) wishes to abort should ideally send a special datagram to the other end to stop the transfer - otherwise the other end will attempt to continue sending/receiving, not knowing that it's on its own. So perhaps a better approach would be to actually send/receive a "cancel transfer" datagram, which would inform the TCP code at both ends that you wish to cancel. (i.e. you wouldn't need to have a special cancel flag, you would simply check if the datagram you are about to send or have just received is a "cancel transfer" datagram). This would allow both ends to gracefully and cleanly close down.

Related

Is it good to handle socket connection status via a timer?

In Server/Client Applications, is it a memory consumption to use a timer that checks for each client if it is connected or not?
For example a Socket Server accepts a Socket Client and add it to a List, then a timer that checks each Client in the List via a loop, if it is not connected then removed from the List<> and fire an event... however though this way sounds hard especially that the timer's interval is 1 second... plus if there let's say 1000 client Connected, can the timer checks them all in 1 second? or should i make it bigger?
I care about the memory used by my app, and the timer capability of checking many clients in 1 sec. is that a true way? thanks in advanced.
No it's not a good idea because it already implements such a mechanism, the Timeout in both send operations and receive operations, meaning that if you set a receive timeout for 10 sec, call the Receive and nothing comes, it will already throw a exception, notifying you as you want to do with the timer...
The last time i created a server/client app like the one you are describing, i created a new thread with priority set a BelowNormal.
The only thing with Timers is that they (potentially) execute inside the UI thread meaning your form will become unresponsive or laggy.
Then i basically looped the thread continuously inside a Do/While loop until the application closed. Throw in a quick Threading.Thread.Sleep(100) and performance will be perfect.
Inside the loop, i'd check for incoming connection requests and like you say, add them to a list etc. You can then also handle communications with each connected client too as it'll have minimal impact.
Private Sub StartSocketsServer()
Try
Dim oThread As New Threading.Thread(AddressOf StartSocketsServer_Threaded)
With oThread
.Name = "Socket Server"
.Priority = Threading.ThreadPriority.BelowNormal
.IsBackground = True
.Start()
End With
Catch ex As Exception
'Handle exception
End Try
End Sub
Private Sub StartSocketsServer_Threaded()
Try
Do
'Perform all of your sockets here in a threaded environment.
Threading.Thread.Sleep(1000) '1 sec
Loop Until Me.IsDisposed
Catch ex As Exception
'Handle thread safe exceptions here
End Try
End Sub

WSAEWOULDBLOCK handling

I have written a socket for a server in C++ CLI that is using winsock. The sockets are using async methods for sending, receiving and accepting connections. After implementing my socket in the production environment, the send function stops working giving me the error WSAEWOULDBLOCK. Out from my research on the net, this means the network buffer for socket IO is full or the networking is too busy to do my operation at this moment. However, I have not seen any specific solution which can address this problem. My temporary solution was to create a do-while loop around the WSASend function, making the thread sleep for X amount of MS and then try again. This resulted in far higher latency than the previous socket (.NET socket class) and large lag spikes.
My code for sending data is as following:
void Connectivity::ConnectionInformation::SendData(unsigned char data[], const int length)
{
if (isClosed || sendError)
return;
Monitor::Enter(this->syncRoot);
try
{
sendInfo->buf = (char*)data;
sendInfo->len = length;
do
{
state = 0;
if (WSASend(connection, sendInfo, 1, bytesSent, 0, NULL, NULL) == SOCKET_ERROR)
{
state = WSAGetLastError();
if (state == WSAEWOULDBLOCK)
{
Thread::Sleep(SleepTime);
//Means the networking is busy and we need to wait a bit for data to be sent
//Might wanna decrease the value since this could potentially lead to lagg
}
else if (state != WSA_IO_PENDING)
{
this->sendError = true;
//The send error bool makes sure that the close function doesn't get called
//during packet processing which could cause a lot of null reffernce exceptions.
}
}
}
while (state == WSAEWOULDBLOCK);
}
finally
{
Monitor::Exit(this->syncRoot);
}
}
Is there a way to use for example the WSAEventSelect method in order to get a callback when I am able to send data? Out from the documentation on MSDN, the wait for data method could also get stuck in this error. Anyone got any solutions for getting around this?
The error code WSAEWOULDBLOCK means that you attempted to operate on a non-blocking socket but the operation could not be completed immediately. This is not a real error - it means that you can retry later or schedule an asynchronous IO (which wouldn't fail). But this is not what you want in the first place. Let me explain:
You are supposed to use sockets in one of two ways:
Synchronous, blocking.
Asynchronous, non-blocking, callback-based.
You are mixing the two which gets you the worst of both. You created a non-blocking socket and use it in a potentially blocking way.
Alas I'm not full qualified to give best-practices for native-code sockets. I suggest you read all of the docs for WSASend because they seem to explain all of this.
Now, why would this strange error code even exist? It is a performance optimization. You can speculatively try to send synchronously (which is very fast). And only if it fails you are supposed to schedule an asynchronous IO. If you don't need that optimization (which you don't) don't do it.
As #usr says, I need to have either LPWSAOVERLAPPED or LPWSAOVERLAPPED_COMPLETION_ROUTINE set to a value in order to make the operation non-blocking. However, after testing, I found out I need t have a LPWSAOVERLAPPED object in order to make the completion routine called. It is also mentioned on MSDN on the documentation of the WSASend function that if the overlapped object and the completion routine is NULL, the socket would behave as a blocking socket.
Thanks, and merry xmas everyone! :)

C# "using" SerialPort transmit with data loss

I'm new to this forum, and I have a question that has been bothering me for a while.
My setup is a serial enabled character display connected to my pc with a usb/uart converter. I'm transmitting bytes to the display via the serialPort class in a separate write buffer thread in a C++ style:
private void transmitThread(){
while(threadAlive){
if(q.Count > 0){ // Queue not empty
byte[] b = q.Dequeue();
s.Write(b,0,b.Length);
System.Threading.Thread.Sleep(100);
}
else{ // Queue empty
System.Threading.Thread.Sleep(10);
}
}
}
Assuming the serial port is already opened, this works perfectly and transmits all the data to the display. There are though no exception handling at all in this snippet. Therefore I was looking into implementing a typical C# feature, the 'using' statement and only opening the port when needed, like so:
private void transmitThread(){
while(threadAlive){
if(q.Count > 0){ // Queue not empty
byte[] b = q.Dequeue();
using(s){ //using the serialPort
s.Open();
s.Write(b,0,b.Length);
s.Close();
}
System.Threading.Thread.Sleep(100);
}
else{ // Queue empty
System.Threading.Thread.Sleep(10);
}
}
}
The problem with this function is, that it only transmits a random amount of the data, typically about one third of the byte-array of 80 bytes. I have tried different priority settings of the thread, but nothing changes.
Am I missing something important, or do I simply close the port too fast after a transmit request?
I hope you can help me. Thanks :)
No, that was a Really Bad Idea. The things that go wrong, roughly in the order you'll encounter them:
the serial port driver discards any bytes left in the transmit buffer that were not yet transmitted when you close the port. Which is what you are seeing now.
the MSDN article for SerialPort.Close() warns that you must "wait a while" before opening the port again. There's an internal worker thread that needs to shut down. The amount of time you have to wait is not specified and is variable, depending on machine load.
closing a port allows another program to grab the port and open it. Serial ports cannot be shared, your program will fail when you try to open it again.
Serial ports were simply not designed to be opened and closed on-the-fly. Only open it at the start of your program, close it when it ends. Not calling Close() at all is quite acceptable and avoids a deadlock scenario.
I think you're missing the point of the using block. A typical using block will look like this:
using (var resource = new SomeResource())
{
resource.DoSomething();
}
The opening happens at the very beginning. Typically as part of the constructor. But sometimes on the first line of the using block.
But the big red flag I see is that the closing happens automatically. You don't need the .Close() call.
If the successful operation of your serial device is dependent on the calls to Thread.Sleep then perhaps the thread is being interrupted at some point, sufficient to make the data transmission out of sync with the device. There would most likely be ways to solve this but the first thing I would do is try to use the .NET SerialPort class instead. The Write method is very similar to what you want to do, and there are C++ code examples in those articles.

C# threading help needed

I've been asked to write a method that will allow a caller to send a command string to a hardware device via the serial port. After sending the command the method must wait for a response from the device, which it then returns to the caller.
To complicate things the hardware device periodically sends unsolicited packets of data to the PC (data that the app must store for reporting). So when I send a serial command, I may receive one or more data packets before receiving the command response.
Other considerations: there may be multiple clients sending serial commands potentially at the same time as this method will form the basis of a WCF service. Also, the method needs to be synchronous (for reasons I won't go into here), so that rules out using a callback to return the response to the client.
Regarding the "multiple clients", I was planning to use a BlockingCollection<> to queue the incoming commands, with a background thread that executes the tasks one at a time, thus avoiding serial port contention.
However I'm not sure how to deal with the incoming serial data. My initial thoughts were to have another background thread that continually reads the serial port, storing data analysis packets, but also looking for command responses. When one is received the thread would somehow return the response data to the method that originally sent the serial command (which has been waiting ever since doing so - remember I have a stipulation that the method is synchronous).
It's this last bit I'm unsure of - how can I get my method to wait until the background thread has received the command's response? And how can I pass the response from the background thread to my waiting method, so it can return it to the caller? I'm new to threading so am I going about this the wrong way?
Thanks in advance
Andy
First of all: When you use the SerialPort class that comes with the framework, the data received event is asynchronous already. When you send something, data is coming in asynchronously.
What I'd try is: queue all requests that need to wait for an answer. In the overall receive handler, check whether the incoming data is the answer for one of the requests. If so, store the reply along with the request information (create some kind of state class for that). All other incoming data is handled normally.
So, how to make the requests wait for an answer? The call that is to send the command and return the reply would create the state object, queue it and also monitor the object to see whether an answer was received. If an answer was received, the call returns the result.
A possible outline could be:
string SendAndWait(string command)
{
StateObject state = new StateObject(command);
state.ReplyReceived = new ManualResetEvent(false);
try
{
SerialPortHandler.Instance.SendRequest(command, state);
state.ReplyReceived.WaitOne();
}
finally
{
state.ReplyReceived.Close();
}
return state.Reply;
}
What's SerialPortHandler? I'd make this a singleton class which contains an Instance property to access the singleton instance. This class does all the serial port stuff. It should also contain an event that is raised when "out of band" information comes in (data that is not a reply to a command).
It also contains the SendRequest method which sends the command to the serial device, stores the state object in an internal list, waits for the command's reply to come in and updates the state object with the reply.
The state object contains a wait handle called ReplyReceived which is set by the SerialPortHandler after it has changed the state object's Reply property. That way you don't need a loop and Thread.Sleep. Also, instead of calling WaitOne() you could call WaitOne(timeout) with timeout being a number of milliseconds to wait for the reply to come in. This way you could implement some kind of timeout-feature.
This is how it could look in SerialPortHandler:
void HandlePossibleCommandReply(string reply)
{
StateObject state = FindStateObjectForReply(reply);
if (state != null)
{
state.Reply = reply;
state.ReplyReceived.Set();
m_internalStateList.Remove(state);
}
}
Please note: This is what I'd try to start with. I'm sure this can be very much optimized, but as you see there's not much "multithreading" involved where - only the SendAndWait method should be called in a way so that multiple clients can issue commands while another client is still waiting for its response.
EDIT
Another note: You're saying that the method should form the basis for a WCF service. This makes things easier, as if you configure the service right, a instance of the service class will be created for every call to the service, so the SendAndWait method would "live" in its own instance of the service and doesn't even need to be re-entrant at all. In that case, you just need to make sure that the SerialPortHandler is always active (=> is created and running independently from the actual WCF service), no matter whether there's currently an instance of your service class at all.
EDIT 2
I changed my sample code to not loop and sleep as suggested in the comments.
If you really want to block until the background thread has received your command response, you could look into having the background thread lock an object when you enqueue your command and return that to you. Next, you wait for the lock and continue:
// in main code:
var locker = mySerialManager.Enquee(command);
lock (locker)
{
// this will only be executed, when mySerialManager unlocks the lock
}
// in SerialManager
public object Enqueue(object command)
{
var locker = new Object();
Monitor.Enter(locker);
// NOTE: Monitor.Exit() gets called when command result
// arrives on serial port
EnqueueCommand(command, locker);
return locker;
}
A couple things. You need to be able to tie up serial responses to the commands that requested them. I assume that there's some index or sequence number that goes out with the command and comes back in the response?
Given that, you should be OK. You need some sort of 'serialAPU' class to represent the request and response. I don't know what these are, maybe just strings, I don't know. The class should have an autoResetEvent as well. Anyway, in your 'DoSerialProtocol()' function, create a serialAPU, load it up with request data, queue it off to the serial thread and wait on the autoResetEvent. When the thread gets the serialAPU, it can store an index/sequence number in the serialAPU, store the serialAPU in a vector and send off the request.
When data comes in, do you protocol stuff and, if the data is a valid response, get the index/sequence from the data and look up the matching value in the serialAPU's in the vector. Remove the matching serialAPU from the vector, load it up with the response data and signal the autoResetEvent. The thread that called 'DoSerialProtocol()' originally will then run on and can handle the response data.
There are lots of 'wiggles' of course. Timeouts is one. I would be tempted to have a state enum in the serialAPU, protected by a CritcalSection or atomicCompareandSwap, initialized ot 'Esubmitted'. If the oringinating thread times out its wait on the autoResetEvent, it tries to set the state enum in its serialAPU to 'EtimedOut'. If it succeeds, fine, it returns an error to the caller. Simlarly, in the serial thread, if it finds a serialAPU whose state is EtimedOut, it just removes it from the container. If it finds the serialAPU that matches response data, it tries to change the state to 'EdataRx' and if it succeeds. fires the autoRestEvent.
Another is the annoying OOB data. If that comes in, create a serialAPU, load in the OOB data, set the state to 'EOOBdata' and call some 'OOBevent' with it.
I would advise you to look at the BackgroundWorker-Class
Ther is a Event in this class (RunWorkerCompleted) which is fired when the worker has finished his job.

How to Read Device Data From serial port

I have one device which sends data on COM port say on COM13. Now i want to read that data and display it in the RichTextBox or in any text control.
I have written the application with the help of IO and IO.Ports but comport.DataRecived event does not fire, even though device is sending data on that port.
I have some software on which i define the port number and it successfully display data, which insure me that data is receiving on the Port but i am unable to receive.
Is there any way i can read data?
comm.Parity = cboParity.Text;//None
comm.StopBits = cboStop.Text;//One
comm.DataBits = cboData.Text;//8
comm.BaudRate = cboBaud.Text;//9600
comm.DisplayWindow = rtbDisplay;//Null
comm.PortName = "COM13";
comm.OpenPort();
cmdOpen.Enabled = false;
cmdClose.Enabled = true;
cmdSend.Enabled = true;
public bool OpenPort()
{
if (comPort.IsOpen)
{
comPort.Close();
}
comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);
comPort.PortName = _portName;
comPort.Open();return true;
}
This normally comes from a wrong configuration of a serial port. It is not enough to simple open a serial port and waiting for some data to come in. You have also to set all the SerialPort.Properties to a correct value for your wanted connection.
Some of the common ones are BaudRate, DataBits or Parity, but to be really sure you have to set all of them. Even such things as RtsEnable or ReadTimeout.
You have to set the all, cause the configuration state will be saved from the port itself. So if one application opens such a port, makes some changes to the configuration and closes it, the next application that opens the port starts with this configuration, till it change it.
Update
Seems to be a problem i can't see from here. ;-))
The only advice i can give you is to use a Monitor tool, to better understand what your other application really does and what comes on the wire. Additionally you can set up two virtual com ports to test reading and writing on one machine (even within the same application), to have a better control about when will which data be send.
Have you read the documentation for the DataReceived event?
From MSDN:
The DataReceived event is not guaranteed to be raised for every byte received. Use the BytesToRead property to determine how much data is left to be read in the buffer.
The DataReceived event is raised on a secondary thread when data is received from the SerialPort object. Because this event is raised on a secondary thread, and not the main thread, attempting to modify some elements in the main thread, such as UI elements, could raise a threading exception. If it is necessary to modify elements in the main Form or Control, post change requests back using Invoke, which will do the work on the proper thread.
The snippet you've posted is quite rough, but I'd set the ReceivedBytesThreshold property to one. This ensures the event firing when at least one byte is present in the incoming buffer.
Cheers
Use PortMon to capture the working software, and then capture your software; then compare the traces. Pay particularly close attention to all the configuration parameters, making sure they are the same (as Oliver mentioned).

Categories