|
Hi!!
Hello every one...
I wanted to know what should i do to keep on listening to multiple ports for msgs and displaying on respective text boxes.
i've tried asych sockets. but cant get it right..
it listens for only one time. if i start a while loop the whole app stops responding..
i hope threading is a answer but i know nothing abt it..
plz guide me..
|
|
|
|
|
Hi,
1.
the question is unclear. What ports? TCP/IP ports? SerialPort instances? ...
2.
regardless, you can handle that with either asynchronous methods and events, or by having some kind of thread and a blocking read.
3.
in any case, you can't touch GUI Controls from threads other than the main thread. So don't try myTextBox.Text="got something"; inside a DataReceived handler. The solution is here[^].
|
|
|
|
|
Ans 1. TCP/IP Ports...
Ans 2. How can i use Threading in GUI app??? i've textbox1 and textbox2. now i need to listen port port1 and port2 and direct the received msgs to their respective textboxes.
Ans 3. thanks for that.. i've studied it already.. that cross thread funcs..
|
|
|
|
|
ayandelhi wrote: How can i use Threading in GUI app???
threading is the same in all kinds of apps, whether GUI, Console, or headless. However to access Controls you need to Invoke.
|
|
|
|
|
I'm lost in it.. i cant see thru it.. when i type a msg in msg text box i shud start a thread which sends it to client n then waits until a msg is received from client. Right.. or something else..
One more thing...
how much time does it take a msg to get delivered from client to server on a lan of max 10 pcs.. i'm asking this coz i want active feed from my clients.. wheneva they type anything on their app it shud be displayed on my window...
|
|
|
|
|
ayandelhi wrote: I'm lost in it.. i cant see thru it.. when i type a msg in msg text box i shud start a thread which sends it to client n then waits until a msg is received from client. Right.. or something else..
I don't see a specific question here. if you are not familiar with the subject, read up on it, think about it, and experiment. when stuck, ask a specific question.
ayandelhi wrote: how much time does it take
42 msec.
how long is your message? how fast is your LAN? what other traffic is there? how inefficient is your code?
if you now some app that does things similar to what you want, then that proves it can be done; if not, it may be an indication it can't be done.
|
|
|
|
|
actually... m running both client n server on my pc.. n m typin on client and it shud be visible as it is.. m sending the text to a file too and to server too.. on file i've complete text but m not getting on the server side.. i want a live feed of wat is the user typing on client not the file.. help me out..
|
|
|
|
|
Luc Pattyn wrote: 42 msec
|
|
|
|
|
Hi I have two application which I have managed to get them to exchange data however, I would like to be able to sort the data out when it is recieved by the other end (server). On the client side, the data is taken from the various forms and sent as below:
String Pname = LblName.Text;
String Pdob = LblDOB.Text;
String PnhsNo = LblNHSno.Text;
String Paddress = RtxtBxAddre.Text;
String PmedicalCon = RtxtBxMedCon.Text;
String pcallOutDetails = RTxtBxCallOut.Text;
byte[] forwardMessage = Encoding.ASCII.GetBytes(Pname + Pdob + PnhsNo + Paddress + PmedicalCon + pcallOutDetails);
sock.Send(forwardMessage);
sock.Shutdown(SocketShutdown.Both);
sock.Close();
On the other end I would now like to take each item and display it in a form, so "Pname" is taken when received and displayed in a text box and then same with the rest of the data. Unlike displaying it in a message box like I have done below:
Socket listener = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.Any, 2112));
listener.Listen(10);
Socket socket = listener.Accept();
string receivedValue = string.Empty;
byte[] receivedBytes = new byte[1024];
int numBytes = socket.Receive(receivedBytes);
receivedValue = Encoding.ASCII.GetString(receivedBytes,0, numBytes);
MessageBox.Show(receivedValue);
listener.Close();
Help....
|
|
|
|
|
You need to put in a delimiter to split the elements at the receiving end. One way to do this would be to use an uncommon character when forming the string, which you can then parse out - don't use a comma just in cast it's present in the input data. I like to use \n in this situation because it's highly unlikely that this will ever be in the input data. Then you simply split the data out at the receiving end using this character sequence.
|
|
|
|
|
Tichaona J wrote: Encoding.ASCII.GetBytes(Pname + Pdob + PnhsNo + Paddress + PmedicalCon + pcallOutDetails);
you can't just concatenate some strings and get away with it, there is no way to separate them again. What if they represent numbers? is 12345 the result of 1 and 2345? or 12 and 345? or...
What you could do is this:
- define a little class that holds the variables (either as strings or, better, as their actual type);
- add [Serializable] attribute;
- make one instance and fill the values from the Form (or whatever your source of information is);
- use XmlSerialize class to turn that object into one XML string;
- transmit that string;
- use XmlSerialize class again to decode the XML string and recreate an instance of your object.
I have an example here[^].
|
|
|
|
|
Luc Pattyn wrote: you can't just concatenate some strings and get away with it
You would be surprised how many people do get away with it thou - running before walking that is, some even just skip both and try to swim - and CP is the bottom of the ocean (help to untie concrete boots - URGENTZ!!!)
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
I have since tried to put the strings into an arraylist but question now is how do you convert the array list into bytes, cause this doesn't work:
patient.Add(Pname);
patient.Add(Pdob);
patient.Add(PnhsNo);
patient.Add(Paddress);
patient.Add(PmedicalCon);
patient.Add(pcallOutDetails);
byte[] forwardMessage = Encoding.ASCII.GetBytes(patient);
sock.Send(forwardMessage);
sock.Shutdown(SocketShutdown.Both);
sock.Close();
|
|
|
|
|
A byte[] is just a bad as a string in that if you want to split it at the other end you need to do some work on it prior to creating it (like give it something to be split by)
Really thou, you should follow Luc's advice - he knows what he is talking about
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
I can't argue with that. Although Pete's approach is fine too under the circumstances (single-line TextBoxes).
|
|
|
|
|
Thanks guys...With you hints and tips I have figured it out. Part of the solution (the code any) came from this site:
msdn library
Once again thanks...
|
|
|
|
|
Dear Friends,
I want to convert a query string object into a datetime in this format:- "YYYY-mm-dd HH:mm:ss.xxx" in C#.net. But when i am using Convert.ToDateTime(object) for getting the datetime value then an exception is being fired.
Could anyone can provide me the iFormatProvider for the same.?
Thanks
Varun Sareen
|
|
|
|
|
Try using DateTime.ParseExact instead MSDN[^]
string dateString, format;
...
DateTime result;
CultureInfo provider = CultureInfo.InvariantCulture;
result = DateTime.ParseExact(dateString, format, provider); You can build your format from the format specifiers: Formatting a DateTime for display format string[^] - they work the other way as well.
Real men don't use instructions. They are only the manufacturers opinion on how to put the thing together.
|
|
|
|
|
Error:
[12/1/2010 4:28:54 PM]: Object passed was not capable of being deserialized. Error: System.Runtime.Serialization.SerializationException: End of Stream encountered before parsing was completed.
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
at JDMonitoring.Listen.Listener.ReadCallback(IAsyncResult iar) in C:\Users\Jacob\documents\visual studio 2010\Projects\JDMonitoring\JDMonitoring\Listen\Listener.cs:line 99
Ok this is for a Client/Server application. I marked my custom object as serializable. The problem is when I changed it from using an array to a generic list. But before I send the data it is being sent as an Array and not a generic list.
CLIENT:
private static List<Commons> pendingCommons;
public static Commons[] PendingTasks
{
get
{
if (Reg.Registered == 0)
SetRegisterDefaults();
if (pendingCommons == null || pendingCommons.Count < 1)
SetCheckinDefaults();
return pendingCommons.ToArray();
}
set
{
pendingCommons = new List<Commons>(value);
}
}
Here is how I'm sending:
Commons[] commons = Tasks.PendingTasks;
MemoryStream ms = new MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(ms, commons);
s.Send(ms.ToArray());
Logging.Log("Transferred " + ms.Length.ToString() + " bytes to server containg these actions: " + Tasks.GetActions(), true);
ms.Dispose();
Ok so I see in my log that it tranferred that to the server so it was able to serialize it. The Tasks.GetActions() shows what was sent
Now here is my server
private void ReadCallback(IAsyncResult iar)
{
StateObject state = iar.AsyncState as StateObject;
Socket handler = state.worker;
try
{
int bytesRead = handler.EndReceive(iar);
if (bytesRead > 0)
{
state.ms.Write(state.buffer, 0, bytesRead);
if (bytesRead == StateObject.BufferSize)
{
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
else
{
Logging.Log("Finished receiving " + state.ms.Length.ToString() + " bytes from " +
handler.RemoteEndPoint.ToString(), true);
state.ms.Seek(0, SeekOrigin.Begin);
IFormatter formatter = new BinaryFormatter();
object receivedObject = null;
try
{
receivedObject = formatter.Deserialize(state.ms);
}
catch (SerializationException se)
{
Logging.Log("Object passed was not capable of being deserialized. Error: " + se.ToString(), false);
}
string agentId = string.Empty;
if (receivedObject != null)
{
if (receivedObject.GetType() == typeof(Commons[]))
{
Commons[] cObject = (Commons[])receivedObject;
if (cObject != null)
{
Tasks.Perform(ref cObject, out agentId);
}
}
else
Logging.Log("Agent did not send back a Commons object", true);
}
else
Logging.Log("Agent " + handler.RemoteEndPoint.ToString() + " sent back null", true);
MemoryStream ms = new MemoryStream();
formatter.Serialize(ms, Commands.GetAgentCommands(agentId));
handler.BeginSend(ms.ToArray(), 0, (int)ms.Length, 0,
new AsyncCallback(SendCallback), handler);
formatter = null;
}
}
}
catch (SocketException)
{
Logging.Log(handler.RemoteEndPoint.ToString() + " has disconnected", true);
}
catch (Exception ex)
{
Logging.Log(ex.ToString(), false);
}
}
So what has changed? I mean it is a Common[] object array before it is sent to the server. It has something with the client converting it from the List<> to an Array.
At first evyerhing was an Array. But I found it was more difficult for me removing and determining if something was null. Had issues, so for now I turned it into a List then back to a array before sending.
BTW this was working before I did the List<commons>. When it was just straight Commons[] everywhere it worked fine.
modified on Wednesday, December 1, 2010 6:04 PM
|
|
|
|
|
What is the relationship between state.buffer where you put the data and state.ms where you attempt to extract it for deserialization?
|
|
|
|
|
Hi Jacob,
I don't see anything wrong with your code, however I doubt your observations are correct. Your client code is turning the List into an array right away, so everything that relates to serializing/deserializing and sending/receiving is unchanged, therefore it should continue to work or continue not to work when switching between arrays and lists.
You could check the number of bytes transferred; they should be identical for arrays and lists; and of course also at the sending and at the receiving end of the cable.
BTW: I don't fully understand the server's if (bytesRead == StateObject.BufferSize) statement; I'm not saying it is wrong, however it looks strange and potentially dangerous as the amount of data depends on the previous receive request, not the current buffer size.
|
|
|
|
|
Luc I think you are right about the StateObject.BufferSize. It really was the only way I could think to do it.
So I'm receiving the data asynchronously. So as you can tell it is doing a loop passing the StateObject until all data is received. I am reading only 1024 bytes.
So lets say I send the server 1048 bytes. The server will read 1024 bytes then call BeginReceive again. Now the server should only receive 24 bytes this next go around due to 1024 + 24 = 1048. So this time it is seeing that it received LESS than 1024 which tells me that we are done receiving all the data.
So lets say we send 2048 (1024 + 1024).. then this code will not work because after the first time it will call begin receive and get 1024 bytes, then it will call it again and receive 1024 bytes, then it will call it a third time and not get any bytes (which won't execute the code and the data is lost.
Hope I explained / understand that correctly. I'm thinking this could be my issue?
|
|
|
|
|
When the data length can vary, there are a couple of ways to cope:
1.
prefix the data with the total length; i.e. first insert an (or a long!) value that specifies total payload length. At the receiver, read the length first, then loop your payload read operations.
2.
alternatively, implement some more elaborate protocol (maybe data packets of a fixed size with a there-is-more flag. This is slightly harder but pays off when you don't know the length in advance.
Your receiver accidentally failing because the payload length was a multiple of 1024 could be very likely up to very unlikely depending on the size of a Common instance; if it is 1024 (or a multiple) then you have the problem for sure; if it is 512B, then you have 50% chance; etc.
But all this does not explain your different list/array behavior...
|
|
|
|
|
Well let me first try to correct the way I am getting the data. I'm going to have to lookup what you are talking about though since I'm not sure how exactly I need to do that since I am just sending and receiving Serialized data and not just text or whatever.
I did leave my laptop at work so I will have to try this tomorrow morning
|
|
|
|
|
two ways: have the length field go through the MemoryStream (may be difficult as you don't know the length yet), or write it to the socket separately. So replace s.Send(ms.ToArray()); by
byte[] bytes=ms.ToArray();
int len=bytes.Length;
s.Send(BitConverter.GetBytes(len));
s.Send(bytes);
plus some similar changes at the receiver of course.
|
|
|
|