I am trying to create TCP IP Client in WPF GUI / C#.NET for a Ubunu Server.
Problem: I am able to connect to the server machine , the connection work correctly, send the message correctly and the ubuntu console show as well , Client Connected and sent this command like Start Video Feed on the server but When it comes to Read the Response nothing happens - It does not read the byte array that should be returned by the Ubuntu Server. Actually on message - 102 it should start the video feed on the server and return back the video feed byte array which should be read further and display the video. No code written yet to display the video feed as I am unable to read the feed from the server however, the client sends the commands(messages) to the server correctly as mentioned can view it on a console of the Ubuntu server machine. Please suggest thanks !!
Below is the code please have a look and suggest me what I am doing wrong :
namespace POC_TCP_Listener
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private int WhichEventFired = 0;
private void Button_Click_1(object sender, RoutedEventArgs e)
{
try
{
// string message = "{Site: 1}";
WhichEventFired = 1; //Start Video Feed
Thread ClientThread = new Thread(new ThreadStart(ConnectToServerAndRetrieveBytes));
ClientThread.Start();
}
catch (Exception ex)
{
string st = ex.Message;
}
}
private void ConnectToServerAndRetrieveBytes()
{
TcpClient TCP = new TcpClient();
TCP.Connect("IPAddress", 5001);
byte[] packet;
var size = 9;
var header = 102;
var siteId = 1;
var state = 1;
if (WhichEventFired == 1)
{
header = 102; // Start Video Feed
}
else if (WhichEventFired == 2)
{
header = 114; // Stop Video Feed
}
else
{
header = 115; // query Temperature
}
// <8> <115> <1>
packet = BitConverter.GetBytes(size).Reverse().Concat(BitConverter.GetBytes(header).Reverse()).Concat(BitConverter.GetBytes(siteId).Reverse()).Concat(BitConverter.GetBytes(state).Reverse()).ToArray();
// Translate the passed message into ASCII and store it as a Byte array.
Byte[] data = packet;
// Get a client stream for reading and writing.
NetworkStream stream = TCP.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
byte[] buffer = new byte[64 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
// In the below line - it stops and nothing happens after it - Please Suggest
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
// return ms.ToArray();
}
stream.Close();
TCP.Close();
}
}
}
strong text
Please suggest why it stops working or let me know if I am doing anything wrong.
I think the problem is that if there are no more packages left, it escapes the while-loop. If you want to check it endlessly you should try using a for. But i am not sure.
Yeah that should be it. If there are no Packages in the moment the while-loop is starting, it terminates itself because there is nothing to read. So you could check if the Ubuntu Server returns you something.
Related
I'm trying to write a C# console app to interface with a PC Miler telnet server. I managed to get this to work in powershell, but my C# code is not working.
static void Main(string[] args)
{
byte[] ReadBuffer = new byte[1024];
string[] stringSeparators = new string[]{"READY"};
try
{
TcpClient Socket = new TcpClient("myServer", 8320);
if (Socket.Connected) {
NetworkStream netStream = Socket.GetStream();
string PCMSResponse = "";
// Check for the READY prompt
if (netStream.CanRead) {
int byteRead = 0;
while (netStream.DataAvailable) {
byteRead = netStream.Read(ReadBuffer, 0, ReadBuffer.Length);
PCMSResponse += Encoding.ASCII.GetString(ReadBuffer, 0 , byteRead).Trim();
}
} else {
Console.WriteLine("Cannot read from myServer");
}
Thread.Sleep(1000);
// Get New Trip
if (netStream.CanWrite) {
Byte[] PCMSCommandBuffer = Encoding.ASCII.GetBytes("PCMSNewTrip");
netStream.Write(PCMSCommandBuffer, 0 , PCMSCommandBuffer.Length);
Thread.Sleep(1000);
} else {
Console.WriteLine("Cannot write to myServer.");
}
if (netStream.CanRead) {
int byteRead = 0;
while (netStream.DataAvailable) {
byteRead = netStream.Read(ReadBuffer, 0, ReadBuffer.Length);
PCMSResponse += Encoding.ASCII.GetString(ReadBuffer, 0, byteRead).Trim();
}
} else {
Console.WriteLine("Cannot read from myServer");
}
string[] ResponseArray = PCMSResponse.Split(stringSeparators, StringSplitOptions.None);
int c = ResponseArray.Length - 2;
string TripID = ResponseArray[c].Replace(System.Environment.NewLine, "").Replace("\0", "");
Console.WriteLine(PCMSResponse);
}
}
catch (SocketException)
{
Console.WriteLine("Unable to connect to server")
}
}
Expected output
ALK PCMILER SERVER READY
pcmsnewtrip
53
READY
Actual output
ALK PCMILER SERVER READY
It seems like I am not actually writing to the server because if I were to write an invalid command to the server I would see an error like this:
ALK PCMILER SERVER READY
pmctripnew
NO SUCH FUNCTION
READY
I know I can write to the socket because I'm not getting my error message Cannot write to myServer.
Not sure what I'm doing wrong. :(
Let me know if you'd also like to see the powershell code.
EDIT - If you're going to edit this post, at least keep the expected output AS EXPECTED! Changing the expected output changes the intent of the post. (EG, if I want apples but you edit my post to ask for oranges, I'm not going to get the correct answer.)
So the issue turns out to be that the NetworkStream.Write method does not end a string with a line terminator. As a result, when I wrote my PCMSCommandBuffer bytes to the stream, the command was never processed by the server (because its waiting for more of the command or the enter key to let it know you're done). My solution was to assign the stream to a StreamWriter. Then I can use the WriteLine method whichdoes send a line terminator.
streamWriter = new StreamWriter(netStream);
// Get New Trip
if (netStream.CanWrite) {
Byte[] PCMSCommandBuffer = Encoding.ASCII.GetBytes("PCMSNewTrip");
//netStream.Write(PCMSCommandBuffer, 0 , PCMSCommandBuffer.Length);
streamWriter.WriteLine("PCMSNewTrip");
//netStream.Flush();
streamWriter.Flush();
Console.WriteLine(PCMSCommandBuffer.Length + " PCMSNewTrip");
Thread.Sleep(1000);
} else {
Console.WriteLine("Cannot write to EW-APP1.");
}
Trupulse 360B - a device that can measure the distance to any object.
It reads the data and sends it in this form:
$PLTIT,HV,HDvalue,units,AZvalue,units,INCvalue, units,SDvalue,units,*csum
I need to get this data on my PC using BLUETOOTH
Application should be written in c #
MANUAL - http://wiki.awf.forst.uni-goettingen.de/wiki/images/7/71/TruPulse_360-B_Users_Manual_2nd_Edition_English.pdf
Thanks!
data is not always there, from 10 times goes 2-3 times normally, in other cases blank lines appear.What am I doing wrong?
private static void Connect(IAsyncResult result)
{
if (result.IsCompleted)
{
// client is connected now :)
Console.WriteLine(BC.Connected);
stream = BC.GetStream();
if (stream.CanRead)
{
byte[] myReadBuffer = new byte[1024];
StringBuilder myCompleteMessage = new StringBuilder();
int numberOfBytesRead = 0;
// Incoming message may be larger than the buffer size.
NmeaParser.StreamDevice truepulse = new NmeaParser.StreamDevice(stream);
truepulse.OpenAsync();
do
{
numberOfBytesRead = stream.Read(myReadBuffer, 0, myReadBuffer.Length);
myCompleteMessage.AppendFormat(Encoding.ASCII.GetString(myReadBuffer));
}
while (stream.DataAvailable);
// Print out the received message to the console.
Console.WriteLine("You received the following message : " + myCompleteMessage);
}
else
{
Console.WriteLine("Sorry. You cannot read from this NetworkStream.");
}
Console.ReadLine();
}
}
I'm working with an Access Control Device, that allows or denies access to rooms, verifying rights through biometric data. I need to listen indefinitely for data on a connected TcpClient(Socket). But how to do this without the following approach:
byte[] bb = new byte[1024]
while(true)
{
if (tcpClient.Client.Available > 0)
{
tcpClient.Client.Receive(bb, bb.Length, SocketFlags.None);
int k = tcpClient.Client.Receive(bb);
string result = Encoding.Default.GetString(bb.Take(k).ToArray());
// do sth here, rise an event, etc...
}
Thread.Sleep(500);
}
I'm following this example, did some adaptation (see below), but only the first chunk of data is read (if the device sends something again, the sent data are not read). I think that the EndReceive method is closing the socket or else, but I want to read the socket continuously, to raise an event every time socket reads data.
...
TcpClient tcpClient // Connected with BeginConnect
byte[] BufferData = new byte[1024]
public IAsyncResult StartReceivingData()
{
//some code here
return tcpClient.Client.BeginReceive(DataBuffer, 0,
DataBuffer.Length, SocketFlags.None,
new AsyncCallback(ReceivedData), tcpClient);
}
public void ReceivedData(IAsyncResult callerResult)
{
TcpClient remote = (TcpClient)callerResult.AsyncState;
int recv = remote.Client.EndReceive(callerResult);
string stringData = Encoding.ASCII.GetString(BufferDados, 0, recv);
//rise an event here containing stringData
}
EDIT
I'm working with .NET 3.5 and I can't upgrade to .NET 4/4.5, because this is part of a legacy system.
TcpClient has a very useful method GetStream. I would use it.
var buf = new byte[0x10000];
var stream = tcpClient.GetStream();
int len = await stream.ReadAsync(buf, 0, buf.Length);
while (len > 0)
{
//your work ....
len = await stream.ReadAsync(buf, 0, buf.Length);
}
If you are getting strings separated by newline chars, then you can also use this
var stream = new StreamReader(tcpClient.GetStream());
string line = await stream.ReadLineAsync();
while (line!=null)
{
//...
line = await stream.ReadLineAsync();
}
EDIT
but only the first chunk of data is read It is because BeginReceive doesn't mean you'll get a callback for every data you receive. You should call it everytime you receive your data (for ex, in ReceivedData method)
I have set up a C# server which at present serves up one test mp3 file over TCP. The code to send the file is as follows
public void RunStreamer()
{
log.MakeLog("Starting streamer");
Run = true;
//Need to look into how to thread this to not block the main window
TcpListener listen = new TcpListener(localAddr, _port);
listen.Start(); //startlistening to client requests
//blocks until a client request comes in
for (; ; )
{
Socket socket = listen.AcceptSocket();
if (socket.Connected)
{
SendFileToClient(socket);
socket.Disconnect(false);
}
}
}
void SendFileToClient(Socket socket)
{
log.MakeLog("Connection made");
NetworkStream netStream = new NetworkStream(socket);
StreamWriter writer = new StreamWriter(netStream);
//Todo - set specfified file - this file just for test
FileStream filestream = File.Open(#"C:\MusicTest\Test.mp3", FileMode.Open, FileAccess.Read, FileShare.Read);
filestream.CopyTo(netStream);
netStream.Flush();
netStream.Close();
}
In my test android set up I am making a call to the server on a button click:
public void btngo_click(View v)
{
final TcpClient client = new TcpClient();
new Thread(new Runnable(){
#Override
public void run() {
final MediaPlayer mediaPlayer = new MediaPlayer();
client.GetStream();
runOnUiThread(new Runnable(){
public void run()
{
int length = client.GetLength();
if(length > 0)
{
byte[] result = client.GetResult();
try {
// create temp file that will hold byte array
File tempMp3 = File.createTempFile("test", "mp3", getCacheDir());
tempMp3.deleteOnExit();
FileOutputStream fos = new FileOutputStream(tempMp3);
fos.write(result);
fos.close();
mediaPlayer.reset();
FileInputStream fis = new FileInputStream(tempMp3);
mediaPlayer.setDataSource(fis.getFD());
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException ex) {
String s = ex.toString();
ex.printStackTrace();
}
}
}
});
}
}).start();
}
the stream is received in the TcpClient class which is as follows:
public class TcpClient {
public final static String SERVER_ADDRESS = "127.0.0.1";
public final static int SERVER_PORT = 65000;
public String TotalResult;
public int Length;
byte[] result = new byte[21000000];
public TcpClient()
{
}
public int GetLength()
{
return Length;
}
public byte[] GetResult()
{
return result;
}
public void GetStream()
{
try
{
final Socket socket = new Socket("192.0.0.5", 85000);
final InputStream input = new BufferedInputStream(socket.getInputStream());
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nread;
while((nread = input.read(result, 0, result.length)) != -1)
{
buffer.write(result, 0, nread);
}
buffer.flush();
//input.read(result);
Length = result.length;
input.close();
socket.close();
} catch (UnknownHostException e) {
String exc = e.getMessage();
e.printStackTrace();
} catch (IOException e) {
String exc2 = e.getMessage();
e.printStackTrace();
}
}
}
With apologies for all the code here is my problem.
I am receiving the stream. The temp MP3 file is created and the media player starts. I then only get a short snippet of the test MP3 file (which is a full song). It also jumps about a bit. The length is not the same and the section of the song played is different each time.
How do I receive the full file in a ordered way such that it will provide full play back of the song.
I have tried to route around for this and have an idea that I need to tell my client what file size it should suspect and then perform some loop until all data is received although I have no idea how to successfully implement this if that is the correct solution.
Any pointers on where I am going wrong or what I can do to rectify would be greatly appreciated!!
Having received no answers on this I dug around a bit more. Two things were wrong:
Firstly I had not included the size of the stream as a int sized header in my stream. I understand that for smaller files this will not be a problem but as file sizes grow it is necessary to make sure that the whole stream has been received.
This in turn raised another issue. The int I was sending as byte[] form c# was not returning the correct value in Java. Turns out Java uses sbytes -128 to 127 range as opposed to byte. This then involved a bit of code to convert to an int. then I could instruct the reader to readfully passing in the byte[] buffer with the actual size of the expected stream = voila it worked. MP3 files is received and plays just fine.
I have implemented my Server application regarding this post here: http://www.codeguru.com/csharp/csharp/cs_network/sockets/article.php/c8781#Client1
Sum up: I am using async Sockets ala BeginAccept(..), BeginReceive(..).
My Server is capable of handling mutliple clients and everything works fine until a client performas two or more synchronous send operation without waiting some time. The client does not get any error and so is not notified, that the server does not get the second message! If the client waits approx. 100ms after the first send operation, everything works fine.
I thought that when i use TCP i can ensure that the server receives the message. (Except there is an exception thrown)!
Could you provide me a solution to fix this.
Here are the WaitForData(..) & OnDataReceive(..) Methods that i implemented in the server
public void WaitForData(MyClient client)
{
try
{
if (pfnCallBack == null)
{
pfnCallBack = new AsyncCallback(OnDataReceived);
}
iarResult = client.Socket.BeginReceive(client.DataBuffer,
0, client.DataBuffer.Length,
SocketFlags.None,
pfnCallBack,
client);
}
catch (SocketException se)
{
MessageBox.Show("SocketException#WaitForData" + se.Message);
}
}
public void OnDataReceived(IAsyncResult asyn)
{
try
{
MyClient user= (MyClient)asyn.AsyncState;
int iRx = user.Socket.EndReceive(asyn);
byte[] receivedData = user.DataBuffer;
MemoryStream memStream = new MemoryStream();
BinaryFormatter binForm = new BinaryFormatter();
memStream.Write(receivedData, 0, receivedData.Length);
memStream.Seek(0, SeekOrigin.Begin);
MyMessage msg = (MyMessage)binForm.Deserialize(memStream);
switch (msg.Command)
{
case (MyMessage.MyCommand.ConnId):
this.connId = (int) msg.MyObject;
tsslConnStatus.Text += " | ID: " + connId.ToString();
break;
case (MyMessage.MyCommand.Text):
MessageBox.Show(msg.MyObject.ToString());
break;
}
WaitForData(server);
}
catch (ObjectDisposedException ode)
{
MessageBox.Show("ObjectDisposedException#OnReceiveData" + ode.Message);
}
catch (SocketException se)
{
MessageBox.Show("SocketException#OnReceiveData" + se.Message);
}
}
The CLIENT calls a synchronous SEND METHOD TWICE or MORE! server INSTANCEOF MyClient
if (server.Socket.Connected)
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, message);
MyMessage = new MyMessage(something);
server.Socket.Send(ms.ToArray());
}
so, i think this code snippets must be enough for you to get the idea i was trying to use!
If you need further details or code snippets, just tell me i will post it!
Thanx!
TCP is stream based and not message based. One Read can contain any of the following alternatives:
A teeny weeny part of message
A half message
Excactly one message
One and a half message
Two messages
Thus you need to use some kind of method to see if a complete message have arrived. The most common methods are:
Add a footer (for instance an empty line) which indicates end of message
Add a fixed length header containing the length of the message
Update
Simple example having just length as header.
Server side:
var buffer = binaryFormmater.Serialize(myobj);
var length = buffer.Length;
networkStream.Send(length);
networkStream.Send(buffer, 0, buffer.Length);
Client side:
var header = new buffer[4];
// TODO: You need to make sure that 4 bytes have been read.
networkStream.Read(header, 0, 4);
var length = BitConverter.ToInt32(buffer);
var readbuffer= new byte[65535];
var bytesLeft = length;
var messageStream = new MemoryStream();
while (bytesLeft > 0)
{
var read = networkStream.Read(readbuffer, 0, bytesLeft);
messageStream.Write(readbuffer, 0, read);
bytesLeft -= read,
}
messageStream.Seek(0, SeekOrigin.Begin);
MyMessage msg = (MyMessage)binForm.Deserialize(messageStream);