Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Socket Server Questions


  • Please log in to reply
6 replies to this topic

#1 pxl357

pxl357

    Member

  • Members
  • PipPip
  • 18 posts

Posted 01 September 2011 - 04:06 AM

Hello all , I finally got my Netduino working on the web fine and start to work on a socket server. So i sucessfully create a server but when i connect to it and send some datas it's directly close the connexion. I mean the client can't send multiple request. I made a super basic example : using System; using System.Threading; using Microsoft.SPOT; using Microsoft.SPOT.Hardware; using SecretLabs.NETMF.Hardware; using SecretLabs.NETMF.Hardware.NetduinoPlus; using Microsoft.SPOT.Net.NetworkInformation; using Microsoft.SPOT.Net; using System.Net.Sockets; using System.Net; using System.Text; namespace NetduinoApplication2 { public class Program { public static void Main() { using (System.Net.Sockets.Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { NetworkInterface networkInterface = NetworkInterface.GetAllNetworkInterfaces()[0]; networkInterface.EnableStaticIP("192.168.1.35", "255.255.255.0", "192.168.1.2"); socket.Bind(new IPEndPoint(IPAddress.Parse("192.168.1.35"), 80)); socket.Listen(1); using (Socket commSocket = socket.Accept()) { if (commSocket.Poll(-1, SelectMode.SelectRead)) { byte[] bytes = new byte[commSocket.Available]; int count = commSocket.Receive(bytes); string request =new String(Encoding.UTF8.GetChars(bytes)); Debug.Print(request); } } } } } } If you send a string to the socket ( after connection ) you can't send a second one. Anyone have an idea how to fix it ? Thanks ! PXL

#2 ColinR

ColinR

    Advanced Member

  • Members
  • PipPipPip
  • 142 posts
  • LocationCape Town, South Africa

Posted 01 September 2011 - 06:48 AM

Paste the code where you send the string to the socket, and then where you try and send the second string.
I can think of two possibilities;

  • You're calling the second request outside of the using block
  • You're sending the content-length in the header, and the browser is closing the connection from it's end after having received the full message.


#3 Cabadam

Cabadam

    Advanced Member

  • Members
  • PipPipPip
  • 90 posts

Posted 01 September 2011 - 03:40 PM

using (Socket commSocket = socket.Accept())
{
if (commSocket.Poll(-1, SelectMode.SelectRead))
{
byte[] bytes = new byte[commSocket.Available];
int count = commSocket.Receive(bytes);
string request =new String(Encoding.UTF8.GetChars(bytes));
Debug.Print(request);
}
}


I think this is the origin of your problem. You create a socket (via Accept), and then you read from that socket. That (usually) will read the first set of bytes your client sends to it. Your code then moves on and exits the using block - which Disposes of the socket (aka: closes it).

Keeping your current structure, I think you could add some sort of loop inside your using() statement. That should ensure your socket stays open between reads.

#4 pxl357

pxl357

    Member

  • Members
  • PipPip
  • 18 posts

Posted 02 September 2011 - 04:18 AM

Great Help thanks for your comments ! So it's finally working , i have one different issue now. When i get the request as a string and try to do something else it's close the connection again. I have an exemple when i use stephan drivers to control 2 motors from 2 basic request ( start /stop ) , in this example ( i put the source as well in my post ) the connection close just after the motor start or stop. Any ideas if i miss something in term of thread management etc ? using System; using Microsoft.SPOT; using System.Net.Sockets; using Microsoft.SPOT.Net.NetworkInformation; using System.Net; using System.Text; using StefanCo.NETMF.Hardware; using SecretLabs.NETMF.Hardware; using SecretLabs.NETMF.Hardware.NetduinoPlus; using System.Threading; using Microsoft.SPOT.Hardware; namespace BetterSocket { public class Server : IDisposable { private Socket socket = null; public Server(string ip, int port) { MotorShield motor = new MotorShield(Pins.GPIO_PIN_D5, Pins.GPIO_PIN_D9, Pins.GPIO_PIN_D6, Pins.GPIO_PIN_D10); NetworkInterface networkInterface = NetworkInterface.GetAllNetworkInterfaces()[0]; networkInterface.EnableStaticIP(ip, "255.255.255.0", "192.168.1.2"); using (System.Net.Sockets.Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { socket.Bind(new IPEndPoint(IPAddress.Parse(ip), port)); Debug.Print("Bind the socket client to " + ip); socket.Listen(1); while (true) { using (Socket currentSocket = socket.Accept()) { bool keepAlive = true; while (keepAlive) { if (currentSocket.Poll(-1, SelectMode.SelectRead)) { byte[] bytes = new byte[currentSocket.Available]; int count = currentSocket.Receive(bytes); string request = new String(Encoding.UTF8.GetChars(bytes)); if (request == "start") { currentSocket.Send(Encoding.UTF8.GetBytes("\r\n" + "Start Engine")); motor.SetState(MotorShield.Motors.Motor1, 10); motor.SetState(MotorShield.Motors.Motor2, 10); keepAlive = false; } else if (request == "stop") { currentSocket.Send(Encoding.UTF8.GetBytes("\r\n" + "You ask for a c")); motor.SetState(MotorShield.Motors.Motor1, 0); motor.SetState(MotorShield.Motors.Motor2, 0); keepAlive = false; } Debug.Print("Request "+request); } } Debug.Print("Server Close"); } } } } #region IDisposable Members public void Dispose() { if (socket != null) socket.Close(); } #endregion } } Thanks ! PXL

#5 Cabadam

Cabadam

    Advanced Member

  • Members
  • PipPipPip
  • 90 posts

Posted 02 September 2011 - 03:16 PM

while (true)
{
using (Socket currentSocket = socket.Accept())
{
bool keepAlive = true;
while (keepAlive)
{

if (currentSocket.Poll(-1, SelectMode.SelectRead))
{
byte[] bytes = new byte[currentSocket.Available];
int count = currentSocket.Receive(bytes);
string request = new String(Encoding.UTF8.GetChars(bytes));
if (request == "start")
{
currentSocket.Send(Encoding.UTF8.GetBytes("\r\n" + "Start Engine"));


motor.SetState(MotorShield.Motors.Motor1, 10);
motor.SetState(MotorShield.Motors.Motor2, 10);
keepAlive = false;

}
else if (request == "stop")
{
currentSocket.Send(Encoding.UTF8.GetBytes("\r\n" + "You ask for a c"));

motor.SetState(MotorShield.Motors.Motor1, 0);
motor.SetState(MotorShield.Motors.Motor2, 0);
keepAlive = false;

}
Debug.Print("Request "+request);
}
}
Debug.Print("Server Close");
}
}


It actually looks like the same problem to me :)

You added a loop inside the using statement, which is good. But as soon as you receive a "start" or "stop" command, you are setting keepAlive to false. That means your loop will execute and your code will leave the "using" block - so the socket gets closed. I'm not exactly sure what you are trying to do with the keepAlive variable, but if you change your code so that you don't set keepAlive to false until you actually want to close the socket, it should work.

#6 Cabadam

Cabadam

    Advanced Member

  • Members
  • PipPipPip
  • 90 posts

Posted 02 September 2011 - 03:22 PM

byte[] bytes = new byte[currentSocket.Available];
int count = currentSocket.Receive(bytes);
string request = new String(Encoding.UTF8.GetChars(bytes));


On a separate note from the problems you have been troubleshooting, I want to caution you about how you are reading commands. I'm not speaking from Netduino experience here, but general .NET socket/networking development (actually, networking in general, not just .net!)

On the client who is sending these "start" and "stop" commands, there may well be a single socket.Send(...) call that sends the "start" text to the Netduino. However - there is no guarantee that your currentSocket.Receive(...) call will return all of it in one read.

It all depends on the network that is between the sender and receiver. MOST of the time, on data that small, it will probably work fine. But sometimes it won't. I have seen one network where we literally got one byte at a time. Ex: The first .Receive() call gave us just the "s", a second call gave us just the "t", third gave us "a", etc.

To handle this, you really need to have some sort of terminator on your commands. That is, "start" should be immediately followed by a CR-LF or something. Or a special non-text character that you know won't show up in the middle of a command (0xFF). Anything! Then when you receive data you have to basically keep reading data and appending it to a buffer until you reach your terminator. THEN you can process the command.

Does that make sense?

Again, you don't seem to be running into it now, but you very well randomly could in the future so I wanted to make you aware of this.

#7 pxl357

pxl357

    Member

  • Members
  • PipPip
  • 18 posts

Posted 03 September 2011 - 05:21 AM

Great help thanks a lot ! I finally made it work , the keep alive only switch to false when a client disconnect. Thanks a lot again !




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.