I am working on a program where I continously send control commands to control the AR.Drone. I am writing the contents to a buffer and sending to a socket.
When I execute the program the drone is not behaving as required. I think this may be due to contents queued in the buffer that were not sent.
So I want to clear the contents of buffer before sending any new command. How can I do this?
In C we can use flush(). What is it in C#?
My code is:
Socket sending_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress send_to = IPAddress.Parse("192.168.1.1");
IPEndPoint sending_end_point = new IPEndPoint(send_to, 5556);
string buff1;
byte[] buff2;
I am writing a string to a text file upon each button press. I then read the text file to retrieve the content and based upon the content send the corresponding command.And in text file each time I am overwriting the previous string so there will be only one string in text file.
switch (choice1)
{
case "takeoff":
{
System.Console.WriteLine("send take-off command");
buff1 = null;
buff2 = null;
buff1 = String.Format("AT*REF={0},290718208\r", seq);
buff2 = Encoding.ASCII.GetBytes(buff1);
sending_socket.SendTo(buff2, sending_end_point);
seq = seq + 1;
break;
So I want to clear the contents of buffer before sending any new command.
In the code shown, you are creating a new buffer each time. There is no need to clear / reset / flush this.
You mention a Socket; in that case, there's a good chance this is Nagle. Try setting:
socket.NoDelay = true;
Note that if you do this, it is your job to perform any necessary buffering prior to sending. Avoid things like:
netStream.Write(oneByte);
netStream.Write(threeBytes);
netStream.Write(twoBytes);
as this will lead to packet fragmentation. If you have existing code like that, a pragmatic fix is to wrap a NetworkStream in a BufferedStream, and Flush() that at the end of logical messages.
Related
I am relativity new to C#. In my TCP client have the following function which sends data to the server and returns the response:
private static TcpClient tcpint = new TcpClient(); //Already initiated and set up
private static NetworkStream stm; //Already initiated and set up
private static String send(String data)
{
//Send data to the server
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(data);
stm.Write(ba, 0, ba.Length);
//Read data from the server
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
//Construct the response from byte array to string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < k; i++)
{
sb.Append(bb[i].ToString());
}
//Return server response
return sb.ToString();
}
As you can see here, when I am reading the response from the server, I am reading it into a fix byte[] array of length 100 bytes.
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
What do i do if the response from the server is more than 100 bytes? How can I read the data without me knowing what the max length of data form the server will be?
Typically, where there is not some specific intrinsic size of something, tcp protocols explicitly send the length of objects they are sending. One possible method for illustration:
size_t data_len = strlen(some_data_blob);
char lenstr[32];
sprintf(lenstr, "%zd\n", data_len);
send(socket, lenstr, strlen(lenstr));
send(socket, some_data_blob, data_len);
then when the receiver reads the length string, it knows exactly how mush data should follow (good programming practice is to trust but verify though -- if there is more or less data really sent -- say by an 'evil actor' -- you need to be prepared to handle that).
Not with respect to C# but a general answer on writing TCP application:
TCP is steam based protocol. It does not maintain message boundaries. So, the applications using TCP should take care of choosing the right method of data exchange between server and client. Its becomes more paramount if multiple messages gets sent and received on one connection.
One widely used method is to prepend the data message with the length bytes.
Ex:
[2 byte -length field][Actual Data].
The receiver of such data (be it server or client needs to decode length field, wait for until such event where as many bytes are received or raise an alarm on timeout and give up.
Another protocol that can be used is to have applications maintain message boundaries.
Ex:
`[START-of-MSG][Actual Data][END-of-MSG]
The reciever has to parse the data for Start-byte and End-byte (predefined by application protocol) and treat anything in between as data of interest.
hello i solved it with a list, i don't know the size of the complete package but i can read it in parts
List<byte> bigbuffer = new List<byte>();
byte[] tempbuffer = new byte[254];
//can be in another size like 1024 etc..
//depend of the data as you sending from de client
//i recommend small size for the correct read of the package
NetworkStream stream = client.GetStream();
while (stream.Read(tempbuffer, 0, tempbuffer.Length) > 0) {
bigbuffer.AddRange(tempbuffer);
}
// now you can convert to a native byte array
byte[] completedbuffer = new byte[bigbuffer.Count];
bigbuffer.CopyTo(completedbuffer);
//Do something with the data
string decodedmsg = Encoding.ASCII.GetString(completedbuffer);
I do this whith images and looks good, i thik than you dont know the size of the data if the porpouse is read a complete source with a unknow size
I was looking around for an answer to this, and noticed the Available property was added to TcpClient. It returns the amount of bytes available to read.
I'm assuming it was added after most of the replies, so I wanted to share it for others that may stumble onto this question.
https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.tcpclient.available?view=netframework-4.8
I am working on Passenger information system PIS(Train).So trains send their location to my server PIS using socket on port 8080 .So i should get their locations and show them to passengers . The message that comes from the trains has a template that i should follow that. As you can see here :
So as you can see here we have 6 variables .every integer is 4 byte. The first variable is(4 byte) message source and etc.
In my server i have to detect these variable but i don't know how can i detect them from the message .
static void Listeners()
{
Socket socketForClient = tcpListener.AcceptSocket();
if (socketForClient.Connected)
{
Console.WriteLine("Client:" + socketForClient.RemoteEndPoint + " now connected to server.");
NetworkStream networkStream = new NetworkStream(socketForClient);
System.IO.StreamWriter streamWriter =
new System.IO.StreamWriter(networkStream);
System.IO.StreamReader streamReader =
new System.IO.StreamReader(networkStream);
while (true)
{
TimeTableRepository objTimeTableRepository = new TimeTableRepository();
SensorRepository objSensorRepository = new SensorRepository();
ArrivalTimeRepository objArrivalTimeRepository=new ArrivalTimeRepository();
TrainRepository objTrainRepository = new TrainRepository();
// OnlineTrainRepository ObjOnlineTrainrepository = new OnlineTrainRepository();
//-----
string theString = streamReader.ReadLine();
}
}
}
Here is my listener to port 8080 and theString is the message that is send by trains.My problem is how can i detect this parameters (Message source,message destination and etc) from theString?I mean i need the value of them to store in database .
best regards
Looks like you don't need to detect anything and definitely should not be slapping this in a string to try and parse.
You already know you are getting a bunch of integers back. You even know what order they are in. Use a BinaryReader to get you your numbers and proceed from there. Once you load your reader up, it should be as simple as calling BinaryReader.ReadInt32() to read the message's numbers one after another.
I must also highly recommend you to look into using statements for your streams.
using (var reader = new BinaryReader(networkStream))
{
var messageSource = reader.ReadInt32();
var messageDestination = reader.ReadInt32();
... and so on ...
}
i'm working with C#, i am connected to a server using one Async TCP socket, the purpose is that the server sends me 5 image files every second.
I took one tutorial about how to make the socket connection, so i think the problem is on the ReadCallBack function. Some jpgs arrive fine but other in a format that windows can't open and i can't understand why.
EDIT: After read different posts and look for more information, i changed completely the way to make that and finally is working fine, if somebody is in the same case, here is how i did it:
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
int cont = 0;
//i'm not sure why i was receiving a "\" character cathing file name, but this will control that
while (state.buffer[cont] != 0x0a && cont < StateObject.BufferSize)
cont++;
string inc_file_name = System.Text.Encoding.ASCII.GetString(state.buffer, 0, cont);
FileStream Fs = new FileStream(inc_file_name, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
int read_cont;
byte [] read_buffer = new byte [1024];
//till end of incoming file
while ((read_cont = handler.Receive(read_buffer)) > 0)
Fs.Write(read_buffer, 0, read_cont);
//save file
Fs.Close();
I hope it helps you.
Thanks for the comments and for your help.
I am writing a C# client application which will connect to the server written in python. My question is about receiving data in loop. The application structure is all about client asks server -> server responds to client. Everything works fine when the message is lower that actual buffer size (set in server). For example: server side buffer: 1024, client buffer size: 256, data length < 1kb. I run my application with following code:
int datacounter = 0;
byte[] recived = new byte[256];
StringBuilder stb = new StringBuilder();
serverStream.ReadTimeout = 1500;
try
{
while ((datacounter = serverStream.Read(recived, 0, 256)) > 0)
{
Console.WriteLine("RECIVED: " + datacounter.ToString());
stb.append(System.Text.Encoding.UTF8.GetString(recived, 0, datacounter));
}
}
catch { Console.WriteLine("Timeout!"); }
Then the application receives data in 4 loops (256 bytes each):
RECIVED: 256
RECIVED: 256
RECIVED: 256
RECIVED: 96
And then the timeout ticks, that ends the transmission and pass the complete data to later analysis (from stb object). I don't think using timeout is proper, but i don't know any other way to do this.
However, this way it works. Here we go with example, that does not:
server side buffer: 1024, client side buffer: 256, data length ~ 8kbytes (python side sends data in loop).
RECIVED: 256
RECIVED: 256
RECIVED: 256
RECIVED: 256
Then the timeout ticks (and obviosly the data is incomplete - got 1kb of 8kb). Sometimes the loop even ends after 1 run with 28 recived bytes and thats all before timeout. Python says that the data has been send properly. Here's the way i create the socket and serverStream object:
TcpClient clientSocket = new TcpClient();
clientSocket.Connect("x.y.z.x", 1234);
NetworkStream serverStream = clientSocket.GetStream();
Its not the TcpClient fault. Tried the same with clear sockets, created like:
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
However that works similar. Is there a way, to make my loop work without timeout, receiving all data? I would like to keep the socket synchronous if possible.
I don't think there's anything wrong with your receive code functionally. I put together a test, and the receiver gets as much as you can send it (eg. 8 MBs), as long as you keep sending without 1.5 seconds pause, before timing out.
So it looks like your server is simply not sending "fast" enough.
To answer your question, timing is not the typical way of knowing when you have received a full message. One common, simple way of determining when a full message is received is to prefix the length of the full message on the sending side (eg. 4-byte int). Then on the receive side, first read 4 bytes, decode to the length, and then read that many more bytes.
You could also consider appending a message termination string, such as Environment.NewLine, to the end of your message. This has the advantage that you could call StreamReader.ReadLine(), which will block until the full message is received. This only works if the termination can NOT be included in the message itself.
If you can't alter the server protocol, is there any other way of knowing you have received a full message? (eg. checking for a NewLine at the end of the message, an XML end tag, or some other pattern.) If not, perhaps you could wait for the server to disconnect, otherwise it looks like you would be forced to find the right timing balance.
I am including the test code below in case you want to play around with it.
Server/Sending Side:
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
TcpListener server = new TcpListener(localAddr, 13579);
server.Start();
TcpClient clientSocket = server.AcceptTcpClient();
NetworkStream stream = clientSocket.GetStream();
int bytesSent = 0;
int bytesToSend = 1 << 25;
int bufferSize = 1024;
string testMessage = new string('X', bufferSize);
byte[] buffer = UTF8Encoding.UTF8.GetBytes(testMessage);
while (bytesSent < bytesToSend)
{
int byteToSendThisRound = Math.Min(bufferSize, bytesToSend - bytesSent);
stream.Write(buffer, 0, byteToSendThisRound);
bytesSent += byteToSendThisRound;
}
Client/Receiving Side:
TcpClient client = new TcpClient("127.0.0.1", 13579);
NetworkStream serverStream = client.GetStream();
int totalBytesReceived = 0;
int datacounter = 0;
byte[] recived = new byte[256];
StringBuilder stb = new StringBuilder();
serverStream.ReadTimeout = 1500;
try
{
while ((datacounter = serverStream.Read(recived, 0, 256)) > 0)
{
totalBytesReceived += 256;
Console.WriteLine("RECIVED: {0}, {1}", datacounter, totalBytesReceived);
stb.Append(System.Text.Encoding.UTF8.GetString(recived, 0, datacounter));
}
}
catch { Console.WriteLine("Timeout!"); }
Why don't you dump the exception that makes your code go into the catch branch and find out? :)
catch (Exception ex) { Console.WriteLine("Timeout because of... " + ex.Message); }
--EDIT
Sorry I didn't see the timout. The question you're asking is if there's a way to do it without timeout. Yes, don't set any timeout and check if received number of bytes is smaller than the buffer size.
That is:
while ((datacounter = serverStream.Read(recived, 0, 256)) > 0)
{
Console.WriteLine("RECIVED: " + datacounter.ToString());
stb.append(System.Text.Encoding.UTF8.GetString(recived, 0, datacounter));
if(datacounter < 256) //you're good to go
break;
}
For anyone else who needs help with this
Just to add to Chi_Town_Don's answer, make sure you use stb.ToString() outside of the loop. And I've found that nothing will print out unless the loop breaks out. To do that if(!serverStream.DataAvailable()){break;} works wonders. That way you don't need to pass in the packet size or some other convoluted condition.
How to send JPG over TCP from one Windows Phone to another?
I found that in the other SO topic(below) showing how to send text over TCP, but how to turn JPG to bytes and send it? Most of jpges are bigger than 4kb how to deal with that?:
private void sendMessage() {
connectArgs = new SocketAsyncEventArgs { RemoteEndPoint = new DnsEndPoint(localIP, Int32.Parse(port)) };
connectArgs.Completed += connectArgs_Completed;
connection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
connection.ConnectAsync(connectArgs);
}
void connectArgs_Completed(object sender, SocketAsyncEventArgs e) {
if (e.SocketError == SocketError.Success && firstLoop) {
firstLoop = false;
var sendArgs = new SocketAsyncEventArgs();
var buffer = Encoding.UTF8.GetBytes("MESSAGE STRING" + Environment.NewLine);
sendArgs.SetBuffer(buffer, 0, buffer.Length);
sendArgs.Completed += sendArgs_Completed;
e.ConnectSocket.SendAsync(sendArgs);
} else {
//blad
}
}
You should probably read the raw image data and send that, along with a special "code" or prefix, and then on the receiving end, save the raw image data to a .jpg file and display that. You can do that with any file.
TCP doesn't limit the size of the packets to 4KB, so that shouldn't be a problem for you. You simply need to read all the image bytes either from file using File.ReadAllBytes or a stream reader, and you then send those bytes across to the receiver.
Alternatively, if you have the image as an object, you could use Marshal.StructureToPtr on the sending end and then use Marshal.PtrToStructure to re-create the image object from the bytes you have received, if you want to show the image directly for example.