I am working with a heat cell with which i can only communicate through Ethernet. When trying to connect to it using sockets, I am stuck on waiting for the Receive() method to end.
I've checked the connection using PuTTY in raw mode and it worked just fine, I was able to send and receive messages.
This led me to believe that I needed to use some kind of raw communication as well, hence why I tried to use SharpPCap and the like. Using this, I am able to read from the cell (although I am faced with a few issues that aren't related to this post).
However, since I'm not very experienced with networking, I was wondering if there was a way to obtain the same results as when I used PuTTY's raw mode but using only Sockets ?
I've come accross this question that was left unanswered, apart from the fact that the author was advised not to use SocketType.Raw.
Below is the example from MSDN documentation that I adapted for my tests. It is supposed to send a request and then listen for the answer.
static void Main(string[] args)
{
System.Net.IPAddress host = System.Net.IPAddress.Parse("10.0.0.3");
int port = 2049;
Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
socket.Connect(host, port);
if (socket.Connected)
{
string request = "99997¶1¶1\\r";
var byteSent = Encoding.Default.GetBytes(request);
var byteReceived = new byte[256];
socket.Send(byteSent, byteSent.Length, 0);
int bytes = 0;
do
{
bytes = socket.Receive(byteReceived, byteReceived.Length, 0); // this is the line I'm being stuck on
} while (bytes > 0);
Console.WriteLine($"Result : {Encoding.Default.GetString(byteReceived)}");
Console.ReadLine();
}
else
{
Console.WriteLine("Connection Failed");
Console.ReadLine();
}
}
UPDATE
I used WireShark to take a look at what was being sent from my application. Turns out the 'CR' and 'LF' werent sent correctly. But correcting this didn't solve my problem.
I can see the server's answer to my request on WireShark, but still I can't read anything using socket.Receive(). Could it be possible that the server is faster to answer than my machine is to start listening ? I tried setting up the socket.ReceiveTimeout property and put my send/receive instructions in a loop, but still nothing returning from the Receive() statement.
The socket is in blocking mode by default (cf Socket.Blocking). That mean that, for your case, blocking until 256 byte has been read (Without timeout by default Socket.ReceiveTimeout).
You may want to set the Blocking mode to false, or set a Receive timeout in order to not block indefinitly.
Alternatively, you may want also to use async method to avoid blocking the main thread.
Related
I have the following code in my Windows phone 8 app.
//connection code, done during app start
socket = new StreamSocket();
await socket.ConnectAsync(serverHostName, serviceName);
dataReader = new DataReader(socket.InputStream);
dataReader.InputStreamOptions = InputStreamOptions.Partial;
dataWriter = new DataWriter(socket.OutputStream);
After the connection is established, I have another thread which checks for incoming network packets
await dataReader.LoadAsync(2048);
dataReader.ReadBytes(buffer);
----------
Workflow is as follows
Phone connects to server using socket.ConnectAsync
Server responds with initial message (Phone receives this properly in dataReader.LoadAsync function)
Phone now sends the 'business specific' request
Server now replies with 'business specific' response (Problem lies here. Phone doesn't receive the reply from server at some of the times).
There is no scenario difference between working state' and 'non working state'.
So I tried to debug this. I put a breakpoint for dataReader.LoadAsync and saw that execution waits infinitely at the call.
To make sure that the server is sending data properly, I ran the app in Windows phone emulator and ran the WireShark network analyzer in the PC. I could see that packets are being received for the IP Address of the phone.
Anyone has any hints on why the dataReader.LoadAsync function call doesn't return at all, when there is data ready to be read in the socket?
I faced the same problem. It is especially bad for Bluetooth RFCOMM SPP serial port devices, because the underlying Rfcomm-object does not provide capabilities for setting ReadTimeout values.
Edit: The InputStreamOptions.Partial option seems to be working UWP Win10 platform, but it is only useful when you are already know much data you are expecting. Otherwise it will wait indefinitely on the last call.
I almost gave up, when I found in references below these lines to solve the problem by using a CancellationTokenSource
//connect your Windows.Devices.Bluetooth.Rfcomm.RfcommDeviceService
// see the Bluetooth chat example
[...]
StreamSocket streamSocket = new StreamSocket();
await streamSocket.ConnectAsync(...); //connect to Bluetooth device
DataReader dataReader = new DataReader(inputStream); // to read from the stream
try
{
var timeoutSource = new CancellationTokenSource(1000); // 1000 ms
uint numberBytesToRead = 256;
var data = await dataReader.LoadAsync(numberBytesToRead).AsTask(timeoutSource.Token);
}
catch (TaskCanceledException)
{
// we will get here, and everything looks fine, but the problem is:
// The underlying streamSocket is also closed!
// we can not re-use the streamSocket. Any more calls to LoadAsync results in exceptions (something about the object being not assigned...)
// we need to do a full await streamSocket.ConnectAsync(...) again, but that takes ~3 seconds.
}
So this method is only a brute-force, last-resort attempt at a time-out.
The method from #mayu works very good (serialDevice.ReadTimeout), but only on devices of class Windows.Devices.SerialCommunication.SerialDevice, but not on
Windows.Devices.Bluetooth.Rfcomm.RfcommDeviceService. I don't know how the situation is for TCP/IP sockets.
In short, is there any usable time-out for RFCOMM SPP Bluetooth connections?
Or any method to know ahead of time if .LoadAsync(1) will block, because no new data is available?
This fellow over at MSDN has the exact same problem, but MS don't know an answer either: https://social.msdn.microsoft.com/Forums/vstudio/en-US/71ea17d4-ca16-43c2-ab43-02d5301def3f/chow-to-set-timeout-on-streamsocketreadasync?forum=wpdevelop
References:
In UWP StreamSocket, can I read data with timeout and leave the connection open if timeout elapses
https://social.msdn.microsoft.com/Forums/en-US/8a5c4fdc-28d6-4a22-8df6-bc519efeaa4d/how-to-control-the-timeout-for-reading-from-streamsocket?forum=winappswithcsharp
DataReader of SocketStream for UWP App
"According to documentation when using InputStreamOptions.Partial, you should use UnconsummedBufferLength instead of an hardcoded value"
That sample seems to be broken.
"await reader.LoadAsync(reader.UnconsumedBufferLength);" is equivalent to
await reader.LoadAsync(0); and then it's not possible to read any data, since you have no buffer to read from.
I'm testing this now and it seems like "reader.InputStreamOptions = Partial;" has no effect at all. My only workaround is to lower the read timeout.
According to documentation when using InputStreamOptions.Partial, you should use UnconsummedBufferLength instead of an hardcoded value :
DataReader reader = new DataReader(clientSocket.InputStream);
// Set inputstream options so that we don't have to know the data size
reader.InputStreamOptions = Partial;
await reader.LoadAsync(reader.UnconsumedBufferLength);
Sample is there
I had a similar problem using Windows Remote Arduino library and SerialUSB stream. I had to change this library and call LoadAsync(1) instead of original LoadAsync(100). Now the code is working fine.
see: https://github.com/ms-iot/remote-wiring/issues/111
For serial devices you need to set
device.ReadTimeout = TimeSpan.FromMilliseconds(100);
for the LoadAsync to return before the buffer is full.
The only way I found to get round not knowing the size of the data before reading was to read one byte at a time until I got a timeout. Feels horrid, but works. Is there a better way yet?
private async Task ReadData(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
DataReaderObject.InputStreamOptions = InputStreamOptions.Partial;
uint data = 0;
uint bufferLength = DataReaderObject.UnconsumedBufferLength;
var timeoutSource = new CancellationTokenSource(100); // 100 ms
try
{
while (true)
{
data = await DataReaderObject.LoadAsync(1).AsTask(timeoutSource.Token);
if (data > 0)
{
String temp = DataReaderObject.ReadString(data);
TemperatureValue.Text += temp.Trim();
}
}
}
catch (Exception)
{
;
}
}
First, I don't know if Stackoverflow is the best site to post this kind of message, but I don't know another sites like this.
In oder to understand properly tcp programmation in C#, I decided to do all possible ways from scratch. Here is what I want to know (not in the right order:
- Simple One Thread Socket Server (this article)
- Simple Multiple Threads Socket Server (I don't know how, cause threads are complicated)
- Simple Thread Socket Server (put the client management in another thread)
- Multiple Threads Socket Server
- Using tcpListener
- Using async / Await
- Using tasks
The ultimate objective is to know how to do the best tcp server, without just copy/paste some parts of come, but understand properly all things.
So, this is my first part : a single thread tcp server.
There is my code, but I don't think anybody will correct something, because it's quite a copy from MSDN : http://msdn.microsoft.com/en-us/library/6y0e13d3(v=vs.110).aspx
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace SimpleOneThreadSocket
{
public class ServerSocket
{
private int _iPport = -1;
private static int BUFFER_SIZE = 1024;
private Socket _listener = null;
public ServerSocket(int iPort)
{
// Create a TCP/IP socket.
this._listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Save the port
this._iPport = iPort;
}
public void Start()
{
byte[] buffer = null;
String sDatasReceived = null;
// Bind the socket to loopback address
try
{
this._listener.Bind(new System.Net.IPEndPoint(System.Net.IPAddress.Loopback, _iPport));
this._listener.Listen(2);
}
catch (Exception e)
{
System.Console.WriteLine(e.ToString());
}
// Listening
try
{
Console.WriteLine("Server listening on 127.0.0.1:" + _iPport);
while (true)
{
Socket client = this._listener.Accept();
Console.WriteLine("Incoming connection from : " + IPAddress.Parse(((IPEndPoint)client.RemoteEndPoint).Address.ToString()) + ":" + ((IPEndPoint)client.RemoteEndPoint).Port.ToString());
// An incoming connection needs to be processed.
while (true)
{
buffer = new byte[BUFFER_SIZE];
int bytesRec = client.Receive(buffer);
sDatasReceived += Encoding.ASCII.GetString(buffer, 0, bytesRec);
if (sDatasReceived.IndexOf("<EOF>") > -1)
{
// Show the data on the console.
Console.WriteLine("Text received : {0}", sDatasReceived);
// Echo the data back to the client.
byte[] msg = Encoding.ASCII.GetBytes(sDatasReceived);
client.Send(msg);
sDatasReceived = "";
buffer = null;
}
else if (sDatasReceived.IndexOf("exit") > -1)
{
client.Shutdown(SocketShutdown.Both);
client.Close();
sDatasReceived = "";
buffer = null;
break;
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}
But I have some questions about that :
Listen Method from Socket have a parameter : backlog. According to MSDN, backlog is the number of available connection. I don't know why, when I put 0, I can connect to my server with multiple Telnet sessions. EDIT : 0 & 1 both allow 2 connections (1 current, 1 pending), 2 allow 3 connections (1 current, 2 pending), etc... So I didn't understand well the meaning of MSDN.
Can you confirm that Accept Method will take each connection one after one, that's why I see text from differents Telnet session in my server ?
Can you confirm (my server is a C# library) I can't kill my server (with this kind of code) without killing the process ? It could be possible with threads but it will come later.
If something is wrong in my code, please help me :)
I will come back soon with a simple multiple thread socket server, but I don't know how (I think one step is available before using threads or async/await).
First off, do your best not to even learn this. If you can possibly use a SignalR server, then do so. There is no such thing as a "simple" socket server at the TCP/IP level.
If you insist on the painful route (i.e., learning proper TCP/IP server design), then there's a lot to learn. First, the MSDN examples are notoriously bad starting points; they barely work and tend to not handle any kind of error conditions, which is absolutely necessary in the real world when working at the TCP/IP level. Think of them as examples of how to call the methods, not examples of socket clients or servers.
I have a TCP/IP FAQ that may help you, including a description of the backlog parameter. This is how many connections the OS will accept on your behalf before your code gets around to accepting them, and it's only a hint anyway.
To answer your other questions: A single call to Accept will accept a single new socket connection. The code as-written has an infinite loop, so it will work like any other infinite loop; it will continue executing until it encounters an exception or its thread is aborted (which happens on process shutdown).
If something is wrong in my code, please help me
Oh, yes. There are lots of things wrong with this code. It's an MSDN socket example, after all. :) Off the top of my head:
The buffer size is an arbitrary value, rather low. I would start at 8K myself, so it's possible to get a full Ethernet packet in a single read.
The Bind explicitly uses the loopback address. OK for playing around, I guess, but remember to set this to IPAddress.Any in the real world.
backlog parameter is OK for testing, but should be int.MaxValue on a true server to enable the dynamic backlog in modern server OSes.
Code will fall through the first catch and attempt to Accept after a Bind/Listen failed.
If any exception occurs (e.g., from Listen or Receive), then the entire server shuts down. Note that a client socket being terminated will result in an exception that should be logged/ignored, but it would stop this server.
The read buffer is re-allocated on each time through the loop, even though the old buffer is never used again.
ASCII is a lossy encoding.
If a client cleanly shuts down without sending <EOF>, then the server enters an infinite busy loop.
Received data is not properly separated into messages; it is possible that the echoed message contains all of one message and part of another. In this particular example it doesn't matter (since it's just an echo server and it's using ASCII instead of a real encoding), but this example hides the fact that you need to handle message framing properly in any real-world application.
The decoding should be done after the message framing. This isn't necessary for ASCII (a lossy encoding), but it's required for any real encodings like UTF8.
Since the server is only either receiving or sending at any time (and never both), it cannot detect or recover from a half-open socket situation. A half-open socket will cause this server to hang.
The server is only capable of a single connection at a time.
That was just after a brief readthrough. There could easily be more.
I am doing some basic Socket messaging. I have a routine that works well but there is a problem under load.
I'm using UDP to do a connectionless SendTo to basically do a ping-like operation to see if any of my listeners are out there on the LAN. Ideally I would just use the broadcast address, but Wireless routers don't seem to relay my broadcast. My work around is to iterate through all IPs on the Subnet and send my data gram to each IP. The other PCs are listening and if they get the message they will reply and that is how I get Peers to find each other. Here is the code that is in the loop which sends the data gram to each IP in the subnet.
string msgStr = "some message here...";
byte[] sendbuf = Encoding.ASCII.GetBytes(msgStr);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.Blocking = true;
socket.SendTo(sendbuf, remoteEndPt);
//socket.Close();
This works, but when the Subnet range is large, say 255.255.0.0 (meaning ~60,000 IPs to iterate through) I will eventually get a SocketException with error code "10022", meaning "Invalid Argument". This tends to happen after ~10,000 or so successful sends then I start to see this error. Also, the router I use at work handles it and is presumably a high powered router, but the cheap-o one in my lab is the one that produces the error.
If I put in a wait time after catching the SocketException and before resuming the loop it will typically recover but eventually I'll get the error again.
I think what is happening is that the buffer on the router gets full and I cannot send anymore data. The higher quality one at work can handle it but the cheap-o one gets bogged down. Does that sound plausible?
A couple questions:
1) When using SendTo in a connectionless manner, do I need to call Close() on my Socket?
I've haven't seen any benefit in calling Close(), but when I do call Close() it severely slows down my iteration (I have it commented out above because it does slow things down a lot). Does this make sense?
2) Is there a way for me to tell I should wait before trying to send more data? It doesn't seem right to just catch the Exception which I still don't know what the cause of it is.
Thanks, J.
I am not sure that is the router only but I suspect that you are also running into some limit in the OS...
Any reason you are creating the Socket every time you send ?
Just reuse it...
Anyways according to http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.aspx it is a good idea to call Shutdown() and then Close() on the Socket... perhaps not with every send but every 255 IPs or so...
Checkout UdpClient - that could make implementation easier / more robust
EDIT - as per comment:
IF you want a Socket reuse "cache"... this for example would make sure that a specific Socket is only used every 256 checks...
// build/fill your Socket-Queue for example in the con
class SocketExample
{
Queue<Socket> a = new Queue<Socket>();
SocketExample ()
{
int ii = 0, C = 256;
for (ii = 0; ii < C; C++)
{
a.Enqueue (new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp));
}
}
// in your function you just dequeue a Socket and use it,
// after you are finished you enqueue it
void CheckNetIP (some parameters...)
{
Socket S = a.Dequeue();
// do whatever you want to do...
// IF there is no exception
a.Enqueue(S);
}
}
I am using the following code (built from answers to my previous questions on SO):
public void Start()
{
listener = new TcpListener(IPAddress.Any, 9030);
listener.Start();
Console.WriteLine("Listening...");
StartAccept();
}
private void StartAccept()
{
listener.BeginAcceptTcpClient(HandleAsyncConnection, listener);
}
private void HandleAsyncConnection(IAsyncResult res)
{
StartAccept();
TcpClient client = listener.EndAcceptTcpClient(res);
StringBuilder sb = new StringBuilder();
var data = new byte[client.ReceiveBufferSize];
using (NetworkStream ns = client.GetStream())
{
int readCount;
while ((readCount = ns.Read(data, 0, client.ReceiveBufferSize)) != 0)
{
sb.Append(Encoding.UTF8.GetString(data, 0, readCount));
}
// Do work
// Test reply
Byte[] replyData = System.Text.Encoding.ASCII.GetBytes(DateTime.Now.ToString());
ns.Write(replyData, 0, replyData.Length);
ns.Flush();
ns.Close();
}
client.Close();
}
The line "Do work" represents where I will do the required processing for my client.
However I can't see how to use this code to read the client's data and then reply to it. When using this code I can read perfectly what is sent by my client, however once that occurs the client locks up and eventually complains that the connection was terminated. It does not receive my reply.
Any ideas on how to fix this?
Okay, first of all, you are mixing asynchronous calls (BeginAcceptTcpClient) and synchronous (Read and Write) calls. That completely kills the purpose of asynchronous code. Second, maybe this is why your socket gets closed ? Performing a sync op on an async socket. I'm not sure, but without the client code it's impossible to tell.
Anyway, this is NOT how you build an asynchronous, multi-client server.
Here is a fully asynchronous server implementation : http://msdn.microsoft.com/en-us/library/fx6588te.aspx
i think you should use a length byte to alloc your buffer. ReceiveBufferSize could be called multiple times, i think there is no gurantee you receive everything in one block.
You have misunderstood how Read works. It blocks until something is received from the other end point. The only time it returns 0 is when the other side have disconnected, hence you will continue reading until the other side disconnects.
When using TCP you need to know when a message ends. You can do that either by sending the message length first as a header or by using a suffix (as a line feed) after each message. Then you should keep reading until the complete message has arrived.
Say I have a TcpClient that I accept from a TcpServer in c#, and for some reason it keeps defaulting with blocking off. Is there some other force that can change how the socket blocking is set? Like say is it affected by the remote connection at all?
I know I set blocking to fale a few builds back, but I changed it, and even introduced the TcpClient instead of a straight socket. I haven't specifically changed the blocking back to true, I just commented blocking = false out. Is that something that persists maybe with the endpoint?
I don't know though it just seemed that as I was programming one day my sockets just became unruley without any real change in their code.
public void GetAcceptedSocket(TcpClient s)
{
try
{
sock = s;
IPEndPoint remoteIpEndPoint = s.Client.RemoteEndPoint as IPEndPoint;
strHost = remoteIpEndPoint.Address.ToString();
intPort = remoteIpEndPoint.Port;
ipEnd = remoteIpEndPoint;
sock.ReceiveTimeout = 10000;
boolConnected = true;
intLastPing = 0;
LastPingSent = DateTime.Now;
LastPingRecieved = DateTime.Now;
handleConnect(strHost, intPort);
oThread = new Thread(new ThreadStart(this.run));
oThread.Start();
}
catch (Exception e)
{
handleError(e, "Connect method: " + e.Message);
}
}
Like say is it affected by the remote
connection at all?
Nope.
It would have been better if you show some code where you create Socket or TcpClient in server side. I cannot find TcpServer class in C#. Are you talking about TcpListener?
If you are, please make it sure that you set Socket's Blocking true if you use AcceptSocket to create a new socket. If you call AcceptTcpClient, you should not worry about blocking or non-blocking mode as TcpClient is always blocking mode.
The TcpClient class provides simple
methods for connecting, sending, and
receiving stream data over a network
in synchronous blocking mode.
from MSDN.
There really is no answer, I've never duplicated this, and after a few months, and a fresh windows install, picked the code up, and didn't have the problem anymore. Very weird though, defiantly couldn't find a programmatic reasoning for it happening. Like I said, after a few months it just kinda worked?
They should really have an 'Unawnserable' option :p.