TCP Send multiple message without closing connection - c#

Hi guys i have build an app for android to get the GPS coordination and i want to send the data to my C# UWP server through TCP. As concept i have opened a socket and i want to send multiple messages without closing the socket.
socket = new java.net.Socket("192.168.2.10", 9999);
printwriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
printwriter.println("message1");
printwriter.println("message2");
printwriter.println("message3");
printwriter.println("message4");
printwriter.flush();
The problem is i only receive message1 or sometimes also messages2 on the server. The other message doesn't show on the server. I don't want to make new connection because i'm planning sending a lot of messages. If any of you know a solution would be appreciated.
I'm currently using the server code for UWP in C# from https://msdn.microsoft.com/en-us/windows/uwp/networking/sockets.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Maps
{
class Connection
{
public async void Connectie()
{
try
{
System.Diagnostics.Debug.WriteLine("Waiting for connection................");
//Create a StreamSocketListener to start listening for TCP connections.
Windows.Networking.Sockets.StreamSocketListener socketListener = new Windows.Networking.Sockets.StreamSocketListener();
//Hook up an event handler to call when connections are received.
socketListener.ConnectionReceived += SocketListener_ConnectionReceived;
//Start listening for incoming TCP connections on the specified port. You can specify any port that' s not currently in use.
await socketListener.BindServiceNameAsync("9999");
System.Diagnostics.Debug.WriteLine("Waiting for connection................");
}
catch (Exception e)
{
//Handle exception.
}
}
private async void SocketListener_ConnectionReceived(Windows.Networking.Sockets.StreamSocketListener sender,
Windows.Networking.Sockets.StreamSocketListenerConnectionReceivedEventArgs args)
{
Stream inStream = args.Socket.InputStream.AsStreamForRead();
StreamReader reader = new StreamReader(inStream);
reader = new StreamReader(args.Socket.InputStream.AsStreamForRead());
System.Diagnostics.Debug.WriteLine("connection................");
//Read line from the remote client.
string request = await reader.ReadLineAsync();
System.Diagnostics.Debug.WriteLine(request);
}
}
}

In addition to what #Hasson said about reading all the lines, you should make sure that you're properly disposing the stream (preferably with a using on the StreamReader, and you could do the same on Stream, although the StreamReader dispose would close it also). It looks like your code is hoping to get the whole message in one call though, so if you don't want to use a while loop that checks !reader.EndOfStream before each ReadLineAsync, you could do something like this:
using (Stream inStream = args.Socket.InputStream.AsStreamForRead())
using (StreamReader reader = new StreamReader(inStream))
{
System.Diagnostics.Debug.WriteLine("connection................");
//Read line from the remote client.
string request = await reader.ReadToEndAsync();
System.Diagnostics.Debug.WriteLine(request);
}
I'm also a little worried about the usage of this class. If the code that instantiates a new Connection() doesn't keep a reference to it available, the garbage collector will gobble it all up and your server won't be listening anymore.
For example, if you're having a button click or a page load doing something like this:
Connection conn = new Connection();
conn.Connectie();
Where there isn't some reference to conn maintained, then after that function is done being called, the garbage collector will automatically dispose it and your StreamSocketListener.

Your server code is incorrect, you have to keep reading in the SocketListener_ConnectionReceived until there is nothing to read, but here you are reading just one line, think about adding a while loop. there are lots of examples for this kind of loop, for example here.

Related

Half-closing TcpClient

I'm having serious issue with half-closing a TcpClient. What I am trying to do is:
On the client:
Send a message
Shutdown the underlying socket for sending
Receive a response
Shutdown the underlying socket for reading (or, at this point, just close it)
On the server:
Receive a message
Shutdown the underlying socket for reading
Send a response
Shutdown the underlying socket for writing (or, at this point, just close it)
However, after the step 2 on either the client, or the server, I can't use the TcpClient's stream.
Here's a very simplified version of my code (without asynchronous calls, processing and cleaning up, and also using StreamReader and StreamWriter instead of an XmlSerializer):
//initialize the connection between the server and the client
var listener = new TcpListener(IPAddress.Any, 13546);
listener.Start();
var client = new TcpClient("127.0.0.1", 13546);
var server = listener.AcceptTcpClient();
listener.Stop();
//CLIENT: send the message
var cwriter = new StreamWriter(client.GetStream());
cwriter.Write("client's message");
cwriter.Flush();
client.Client.Shutdown(SocketShutdown.Send);
//SERVER: receive the message
string msg;
var sreader = new StreamReader(server.GetStream());
msg = sreader.ReadToEnd();
server.Client.Shutdown(SocketShutdown.Receive);
//SERVER: send a response
//Here the code fails on server.GetStream() -
//InvalidOperationException, apparently the whole connection is closed now
var swriter = new StreamWriter(server.GetStream());
swriter.Write(msg + " with server's response");
swriter.Flush();
server.Client.Shutdown(SocketShutdown.Send);
//CLIENT: receive the message
var creader = new StreamReader(client.GetStream());
var response = creader.ReadToEnd();
client.Client.Shutdown(SocketShutdown.Receive);
Is there any way to do this without using a raw socket? Is there something I'm getting wrong?
The problem is that ReadToEnd reads data up to the end of stream. By issuing Client.Shutdown you actually close the socket making it impossible to reuse it (at least in case of TCPClient). Here's the code of GetStream()
public NetworkStream GetStream() {
if(Logging.On)Logging.Enter(Logging.Sockets, this, "GetStream", "");
if (m_CleanedUp){
throw new ObjectDisposedException(this.GetType().FullName);
}
if (!Client.Connected) {
throw new InvalidOperationException(SR.GetString(SR.net_notconnected));
}
if (m_DataStream==null) {
m_DataStream = new NetworkStream(Client, true);
}
if(Logging.On)Logging.Exit(Logging.Sockets, this, "GetStream", m_DataStream);
return m_DataStream;
}
As you can see, the error occures due to closed socket.
EDIT: It is ridiculously strange but I think I found the reason why it doesn't work properly. The reason is that Shutdown always sets flags for the entire socket as disconnected. Even though we are actually not closing it that way! If we preserve stream at the begining of the method we will not face this problem since the problem lies in GetStream method which checks socket's state. But we are probably exposed to some bugs when other code would check socket's state.

C# Tcp Server client Disconnecting problems

Whenever a client Disconnects, the server crashes. Here's the code for the server
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;
using System.Threading;
namespace C_Sharp_Testting
{
class Server
{
private static TcpListener tcpListener;
private static List<TcpClient> tcpClientsList = new List<TcpClient>();
static void Main(string[] args)
{
tcpListener = new TcpListener(IPAddress.Any, 1234);
tcpListener.Start();
Console.WriteLine("Server started");
while (true)
{
TcpClient tcpClient = tcpListener.AcceptTcpClient();
tcpClientsList.Add(tcpClient);
Thread thread = new Thread(ClientListener);
thread.Start(tcpClient);
}
}
public static void ClientListener(object obj)
{
TcpClient tcpClient = (TcpClient)obj;
StreamReader reader = new StreamReader(tcpClient.GetStream());
Console.WriteLine("Client connected");
while (true)
{
string message = reader.ReadLine();
BroadCast(message, tcpClient);
Console.WriteLine(">>> "+message);
}
}
public static void BroadCast(string msg, TcpClient excludeClient)
{
foreach (TcpClient client in tcpClientsList)
{
if (client != excludeClient)
{
StreamWriter sWriter = new StreamWriter(client.GetStream());
sWriter.WriteLine(">>> "+msg);
sWriter.Flush();
}
}
}
}
}
I've already tried closing the reader and tcpClient, but none of them worked.
The thing that initially hits me is that you have not added any error handling to this code.
When you try to read from a disconnected socket, you will encounter an exception, which will crash your application.
You add a try and catch statement to the ClientListener method, to allow each Socket the ability to manage and handle its own errors.
This means you will be able to detect disconnects and handle them gracefully.
Consider implementing events.
Create an event called OnDisconnect, and then add your own handler to the event to remove the disconnected client from the list of clients.
/// <summary>
/// Event is triggered when the peer is disconnecting
/// </summary>
public event DisconnectHandler OnDisconnect;
public delegate void DisconnectHandler(Peer p);
This is an extension class
static class SocketExtensions
{
/// <summary>
/// Extension method to tell if the Socket REALLY is closed
/// </summary>
/// <param name="socket"></param>
/// <returns></returns>
public static bool IsConnected(this Socket socket)
{
try
{
return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
}
catch (SocketException) { return false; }
}
}
Pseudocode below:
if (PeerStream.CanRead)
{
//networkStream.Read(byteLen, 0, 8)
byte[] byteLen = new byte[8];
if (_client.Client.IsConnected() == false)
{
//Fire Disconnect event
if (OnDisconnect != null)
{
disconnected = true;
OnDisconnect(this);
return null;
}
}
while (len == 0)
{
PeerStream.Read(byteLen, 0, 8);
len = BitConverter.ToInt32(byteLen, 0);
}
data = new byte[len];
PeerStream.Read(data, receivedDataLength, len);
return data;
There are many things wrong with your code. At a guess, I would say the primary reason for the crash is that you are adding TcpClients to a list but never removing them. That means regardless of client disconnects, your code still tries to access every TcpClient that ever connected.
On top of that, the code is inherently thread-unsafe. You are adding items to a list in one thread while using a foreach loop to iterate over the list at the same time in a different thread - this will almost certainly result in an exception being thrown.
Lastly, there's no try-catch blocks. If your code is crashing, a simple improvement is to wrap the problem areas with try-catch blocks and handle/log/examine the exceptions when they occur.
You don't have any code to detect that any of the clients have closed its connection. You keep doing reader.Readline. But that won't work. You should use a networkstream instead and check for receiving 0 bytes which indicates the client has closed its end of the connection. It is either this or using exceptionhandling. But receiving 0 bytes is not really an error condition. IMHO you should not use exceptions to capture normal logic flow but real errors. This does not mean you don't have to wrap everything in a try catch block though. You still have to do that too.
from https://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.read(v=vs.110).aspx:
This method reads data into the buffer parameter and returns the number of bytes successfully read. If no data is available for reading, the Read method returns 0. The Read operation reads as much data as is available, up to the number of bytes specified by the size parameter. If the remote host shuts down the connection, and all available data has been received, the Read method completes immediately and return zero bytes.'
When a client disconnects and detected properly you can do all that is needed to make it work properly, like removing it from the list, letting the thread terminate and so on.
Note also that the tcpClientsList needs some kind of semaphore protection otherwise multiple threads are accessing this same list which can lead to strange behavior that happens only now and then.

C# tcp stream - is it possible to run stream without listener?

I want to write a part of code in which I start sending packages using tcp stream, but without any part that receives it over the internet.
In the meantime I would also like to have another method that can connect to that particular stream at any time and starts receiving bytes from the moment it connects.
I wanted to use multicasting, but I see it's impossible to do it over the Internet
Is there a way to do it? I only found some info so far, that the tcp connection in C# uses point to point way, so my case sounds impossible to implement, because the listener has to be always active to even initialize the streamer, how can I bypass that?
Edit Added an example of a simply "broker" who republishes all messages it receives.
Either use UDP and broadcast your packets to an endpoint that may or maynot be listening at any point in time.
Or use a message queue such as MSMQ, RabbitMQ or 0MQ.
MSMQ may become a problem if the listening service is offline for to long as the messages queue on your dispatch system resulting in a backlog that may fill.
If you would like to create something using UDP here is some code.
Listener (server):
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace UDPLISTENER
{
class Program
{
static void Main(string[] args)
{
var port = 8750;
var listener = new UdpClient(port);
var group = new IPEndPoint(IPAddress.Any, port);
Console.WriteLine("Listening for datagrams on port {0}", port);
while(true)
{
var data = listener.Receive(ref group);
Console.WriteLine("{0}: {1}", group.ToString(), Encoding.Default.GetString(data, 0, data.Length));
}
}
}
}
Broker (Server&Client):
sing System;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace UDPCLIENT
{
class Program
{
static void Main(string[] args)
{
int listeningPort = 8749, dispatchPort = 8750;
var listener = new UdpClient(listeningPort);
var group = new IPEndPoint(IPAddress.Any, listeningPort);
// Republish client
var sender = new UdpClient("127.0.0.1", dispatchPort);
Console.WriteLine("Listening for datagrams on port {0}", listeningPort);
while (true)
{
var data = listener.Receive(ref group);
Console.WriteLine("{0}: {1}", group.ToString(), Encoding.Default.GetString(data, 0, data.Length));
sender.Send(data, data.Length);
}
}
}
}
Sender (Client):
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace UDPSENDER
{
class Program
{
static void Main(string[] args)
{
var sender = new UdpClient("127.0.0.1", 8749);
while (true)
{
Console.WriteLine("Message: ");
var data = Encoding.Default.GetBytes(Console.ReadLine());
sender.Send(data, data.Length);
}
}
}
}
Depending what you wish to archive I recommend message queues they give to the most flexibility.
But as you can see UDP works a bit differently to TCP. You don't need a handshake like TCP does, this means if no one is listening to your messages they vanish with no cost to the sender (there is still cost to the network). But if a listener pops up then they start consuming the messages right away. Remember no UDP packet is guaranteed delivery, this is both a blessing and a curse.
If you want messages to be guaranteed you need to implement your own solution, one method is a counter on the datagrams that the listener watches if there is a message missing then it request that message be resent.
You can create a new class derived from Stream, override the Write method, and manage the writing to the tcp clients here. You will be able to write to this stream from your code whether a client is connected or not. When no client is connected, the data will simply be ignored.

Metro app using socketstream to write to Win32 TCPListener in C#

Last year I wrote a home automation application that i could use to control a server from a laptop - the server application used the following resources
using System.Net;
using System.Net.Sockets;
using System.IO;
And then created TCPListener to recieve commands from a local network.
TcpListener server = new TcpListener(localAddr, port);
// Start listening for client requests.
server.Start();
// Buffer for reading data
Byte[] bytes = new Byte[256];
String data = null;
while (true)
{
TcpClient client = server.AcceptTcpClient();
data = null;
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream();
then processing the stream for correct command and parameters and this worked ok for both the client and server.
I started writing a metro app for the remote control, and because of this, I've had to use
using Windows.Networking.Sockets;
using Windows.Networking;
Then created an async void to send the command. (sorry this is very messy)
async void sendTest()
{
StreamSocket socket = new StreamSocket();
await socket.ConnectAsync(new HostName("192.168.88.1"), "13000",SocketProtectionLevel.PlainSocket);
DataWriter writer;
writer = new DataWriter(socket.OutputStream);
// Write first the length of the string as UINT32 value followed up by the string. Writing data to the writer will just store data in memory.
string stringToSend = "Hello";
writer.WriteUInt32(writer.MeasureString(stringToSend));
writer.WriteString(stringToSend);
await writer.StoreAsync();
}
I get an exception (no response in the timeout period)
I know my server is not giving a response, but i've tried a number of things such as AcceptSocket, however these still don't detect that the client has connected.
I'm wondering if Metro has another network library that I can use, or whether someone can suggest an alternative code for my server Listener.
Thanks in advance
Is seems you are looking for a StreamSocketListener. What about this?
private StreamSocketListener listener;
private async void Test()
{
listener = new StreamSocketListener();
listener.ConnectionReceived += OnConnection;
await listener.BindServiceNameAsync(port.ToString());
}
private async void OnConnection(StreamSocketListener sender,
StreamSocketListenerConnectionReceivedEventArgs args)
{
// Streams for reading a writing.
DataReader reader = new DataReader(listener.InputStream);
DataWriter writer = new DataWriter(socket.OutputStream);
writer.WriteString("Hello");
await writer.StoreAsync();
}

c# Serialport problem: data are send in "clumps"

I am trying to remote control a lego mindstorms NXT robot using a bluetooth serial connection. The program connects without any problem but when i send single commands they do not appear before several other commands has been send. Then they all appear at once on the nxt.
I have tried everything (i can think of or google has told me to) but i cannot seam to get the buffer to flush after a command is send.
Anyone having a idea about what i can do?
Here is my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
namespace NXTBtRemote
{
public class BTHandler
{
SerialPort comm;
private string comPort;
public BTHandler()
{
comm = new SerialPort();
}
public Boolean Connect(string _comPort)
{
this.comPort = _comPort;
comm.PortName = comPort;
comm.Open();
if (comm.IsOpen) return true;
else return false;
}
public void sendCommand(Command command)
{
string msg = command.cmdType + "#" + command.arguments;
if (!comm.IsOpen) comm.Open();
comm.WriteLine(msg);
comm.DiscardOutBuffer();
}
}
}
Hope somone can help. Thanks in advance
kind regards - kenneth
comm.DiscardOutBuffer();
That's very bad. You are throwing away the bytes you have just written. The WriteLine() method writes the command to the output buffer from which they are slowly written to the serial port. Only if you debug the code, single stepping through the code, would the serial port driver have enough of a chance to actually send something. It would be hit or miss if the chip itself has a FIFO buffer. Just delete the DiscardOutBuffer() call, it does nothing but harm.
Beyond that, you are really complaining about a problem with receiving a response. But didn't show any code that makes any Read call.

Categories