Socket writing not working properly c# - c#

I'm working on a biometry system with my C# application.
Sdk provices a connection via TCP/IP on port 2100, and works by receiving and sending strings to communicate .
My class:
class Biometry
{
private System.Net.Sockets.TcpClient _clientSocket = new System.Net.Sockets.TcpClient();
public Biometry() {
//connect to socket
_clientSocket.Connect("127.0.0.1", 2100);
_clientSocket.ReceiveTimeout = 9000;
}
public String identify(String msg) {
//get network stream
NetworkStream _serverStream = _clientSocket.GetStream();
//send an array of bites that represents a string(encoded)
System.Text.ASCIIEncoding ASCII = new System.Text.ASCIIEncoding();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(msg);
_serverStream.Write(outStream, 0, outStream.Length);
//reads the response from networkStream
byte[] inStream = new byte[10025];
_serverStream.Read(inStream, 0, (int)_clientSocket.ReceiveBufferSize);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
_serverStream.Close();
return returndata;
}
}
The problem is:
It is not working!! The biometry only works(SDK only understand my request) when I close the application(connection is closed).

You might need to flush the stream before your start reading using _serverStream.Flush().
Another problem might be that in your question you say you need to connect to port 21000, but in your code you connect to 2100, which might be a typo in either place, but should be fixed ;-)
In addition to flushing the stream, your server might also be waiting for an "end of message" indicator?

Related

How can I send multiple string messages from client to server using a single instance of TcpClient?

I have separate client and server console apps. I'm simply trying to send a string from the client to the server and have the server write the string to the console using TcpClient. I can send a single message just fine but when I throw a while loop into the client app to try and send multiple messages without closing the TcpClient, the server doesn't write anything to the console.
//Server
using (TcpClient client = listener.AcceptTcpClient())
{
NetworkStream ns = client.GetStream();
byte[] buffer = new byte[1024];
while (true)
{
if (ns.DataAvailable)
{
int bytesRead = 0;
string dataReceived = "";
do
{
bytesRead = ns.Read(buffer, 0, buffer.Length);
dataReceived += Encoding.UTF8.GetString(buffer, 0, bytesRead);
}
while (bytesRead > 0);
Console.WriteLine($"Message:{ dataReceived }\n");
}
}
}
//Client
using (TcpClient client = new TcpClient(hostname, port))
{
if (client.Connected)
{
Console.WriteLine("Connected to server");
NetworkStream ns = client.GetStream();
string message = "";
//Removing this while loop I can send a single message that the server will write to console
//but with the loop present the server does not write anything
while (true)
{
message = Console.ReadLine();
byte[] messageBytes = UTF8Encoding.UTF8.GetBytes(message);
ns.Write(messageBytes);
Console.WriteLine($"Message Sent! ({ messageBytes.Length } bytes)");
}
}
}
I'm interested in learning sockets and have been pouring over SO questions and MSDN docs for two days but cannot figure out why it's not working as I intend. I feel a bit silly even submitting a question because I'm sure it's something basic I'm not understanding. Could someone please drop some knowledge on me?
SOLUTION
//Server
using (TcpClient client = listener.AcceptTcpClient())
{
NetworkStream ns = client.GetStream();
StreamReader sr = new StreamReader(ns);
string message = "";
while (true)
{
message = sr.ReadLine();
Console.WriteLine(message);
}
}
//Client
using (TcpClient client = new TcpClient(hostname, port))
{
if (client.Connected)
{
Console.WriteLine("Connected to server");
NetworkStream ns = client.GetStream();
StreamWriter sw = new StreamWriter(ns) {Autoflush = true};
string message = "";
while (true)
{
message = Console.ReadLine();
sw.WriteLine(message);
}
}
}
If you debug your server, you'll see that it does receive data. You're just not displaying the data, because the only output your server does is after the loop when the byte count returned is 0: Console.WriteLine($"Message:{ dataReceived }\n");. The byte count will only be 0 when the underlying socket has been shutdown. That never happens because your client is stuck in an infinite loop.
A better approach, for a simple text-based client/server example like this, is to use StreamWriter and StreamReader with line-based messages, i.e. WriteLine() and ReadLine(). Then the line breaks serve as the message delimited, and your server can write the message each time it receives a new line.
Note also that in your example above, you are assuming that each chunk of data contains only complete characters. But you're using UTF8 where characters can be two or more bytes, and TCP doesn't guarantee how bytes that are sent are grouped. Using StreamWriter and StreamReader will fix this bug too, but if you wanted to do it explicitly yourself, you can use the Decoder class, which will buffer partial characters.
For some examples of how to correctly implement a simple client/server network program like that, see posts like these:
.NET Simple chat server example
C# multithreading chat server, handle disconnect
C# TcpClient: Send serialized objects using separators?

Sending String over TCP/IP uisng C#

I have a robotic system that can be interacted with over TCP/IP. I have been able to control the system in Matlab using the following code:
AT = tcpip('cim-up',8000);
fopen(AT);
fprintf(AT, '$global[1] = 33');
I need to emulate the same command in C#. I have tried the following code:
// Connect to Robot using TCPIP
string IP = "cim-up";
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
try
{
tcpclnt.Connect(IP, 8000);
Console.WriteLine("Connected");
}
catch
{
Console.WriteLine("Failed");
}
StreamWriter AT_writer = new StreamWriter(tcpclnt.GetStream(), Encoding.ASCII);
AT_writer.Write("$global[1]=33");
This code will connect to the TCP/IP address but the server does not respond to the $global[1]=33 command.
I have also tried the following:
Byte[] data = System.Text.Encoding.ASCII.GetBytes("$global[1]=33");
// Get a client stream for reading and writing.
NetworkStream stream = tcpclnt.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
Does anyone have any suggestions as I have a successful Matlab implementation?
Thanks

Send and Receive TCP socket android client

I wrote c# client-server application, server is sending data using socket.send(byte[]) and receive using socket.receive(byte[]) now i want to send and receive from android and totally new to android.
i appreciate any kind of help.
//client side
Socket sendChannel=new Socket("localhost", 12345);
OutputStream writer=sendChannel.getOutputStream();
writer.write(new byte[]{1});
writer.flush();
InputStream reader=sendChannel.getInputStream();
byte array[]=new byte[1];
int i=reader.read(array);
//server side
ServerSocket s=new ServerSocket(12345);
Socket receiveChannel = s.accept();
OutputStream writerServer=receiveChannel.getOutputStream();
writer.write(new byte[]{1});
writer.flush();
InputStream readerServer=receiveChannel.getInputStream();
byte array2[]=new byte[1];
int i2=reader.read(array);
You can use a TCP socket and a input stream to read data in a separate thread from the main application thread in your android app like this:
// Start a thread
new Thread(new Runnable() {
#Override
public void run() {
// Open a socket to the server
Socket socket = new Socket("192.168.1.1", 80);
// Get the stream from which to read data from
// the server
InputStream is = socket.getInputStream();
// Buffer the input stream
BufferedInputStream bis = new BufferedInputStream(is);
// Create a buffer in which to store the data
byte[] buffer = new byte[1024];
// Read in 8 bytes into the first 8 bytes in buffer
int countBytesRead = bis.read(buffer, 0, 8);
// Do something with the data
// Get the output stream from the socket to write data back to the server
OutputStream os = socket.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(os);
// Write the same 8 bytes at the beginning of the buffer back to the server
bos.write(buffer, 0, 8);
// Flush the data in the socket to the server
bos.flush();
// Close the socket
socket.close();
}
});
You can wrap the input stream in various other types of stream if you want to read in multibyte values such as shorts or ints (DataInputStream). These will take care of converting from network endianess to the native endianess of the client.
You can get an output stream from the socket to write data back to the server.
Hope this helps.

comparing values sent to/from server by NetworkStream

When u know why the sent string "kamote" to server and the string received "kamote" from server are not the same..
CLIENT
tcpClient = new TcpClient();
tcpClient.Connect(ServerIP, Port);
connectionState = (HandShake("kamote", tcpClient)) ? "Connected to " + ServerIP.ToString() : "Host unreachable.";
private bool HandShake(String str, TcpClient tcpClient)
{
using (NetworkStream ns = tcpClient.GetStream())
{
byte[] toServer = Encoding.ASCII.GetBytes(str);
ns.Write(toServer,0,toServer.Length);
ns.Flush();
byte[] fromServer = new byte[10025];
ns.Read(fromServer, 0, (int)tcpClient.ReceiveBufferSize);
return Encoding.ASCII.GetString(fromServer).Equals(str);
}
}
SERVER
TcpClient tcpClient = new TcpClient();
tcpClient = tcpListener.AcceptTcpClient();
NetworkStream ns = tcpClient.GetStream();
byte[] fromClient = new byte[10025];
ns.Read(fromClient, 0, (int)tcpClient.ReceiveBufferSize);
byte[] toClient = fromClient;
ns.Write(toClient, 0, toClient.Length);
ns.Flush();
Client sent "kamote"
Server received "kamote"
Server sent "kamote"
Client received "kamote"
HandShake() always returns false. How can I fix this?
As in the previous question you asked, you're not keeping track of the number of bytes you received. So what's happening is this:
On the client, you send the string "kamote".
On the server, it receives that string into a buffer that's 10025 bytes long.
The server then sends the entire buffer back to the client -- all 10025 bytes
The client receives all or part of those 10025 bytes and converts them to a string.
The string that gets converted is really "kamote" with a bunch of 0's after it.
You must use the return value from Read to know how many bytes you received.
Did you try limiting the string length to the actual read bytes like this:
noOfBytes = ns.Read(bytes, 0, ...);
Encoding.ASCII.GetString(bytes, 0, noOfBytes);
You are including a lot of 0 characters, since you are including the entire fromServer in getstring. 0s don't print, but they are there. You must tell it the correct number of bytes to decode.

How to send length of a package via tcp/ip protocol

I'm doing this for one of my school projects. I'm trying to design a multi-threaded server that accepts clients for working with a database (adding, deleting records etc). When I connect the client to the server I want to receive all the students in my database.
I access the database on the Server Side and store the information in an ArrayList, which I'm trying to send it over the network. I don't have any knowledge on XMLserializing so I'm trying to send each string in the arrayList to the client. When I send the data from the server, I sometimes receive all the data in the same time, sometimes I don't, so my first guess was that I have to split the data I send into packages of some length. I don't see how can I add the length at the beginning of a package. Wouldn't it be the same thing? Maybe I get the correct length maybe I don't.
Here is my code; I didn't try sending the length of each package yet, because I have no idea how. I tried sending from the server the length of the arraylist, and read from the network stream that many times, but it doesn't work ( I receive all data in one package).
Server side:
private void HandleClient(object client)
{
try
{
ClientNo++;
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] bytes = new byte[4096];
int i;
// Robot r = new Robot();
Protocol p = new Protocol();
ArrayList ListaStudentiResponse = p.ExecuteQueryOnStudents("select * from studenti");
byte[] Length = new byte[4];
Length = System.Text.Encoding.ASCII.GetBytes(ListaStudentiResponse.Count.ToString());
clientStream.Write(Length, 0, Length.Length);
foreach ( String s in ListaStudentiResponse)
{
byte[] data = System.Text.Encoding.ASCII.GetBytes(s);
clientStream.Write(data, 0, data.Length);
}
tcpClient.Close();
ClientNo--;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
On Client:
private void connectToServerToolStripMenuItem_Click(object sender, EventArgs e)
{
tcpclient = new TcpClient();
NetworkStream netStream;
try
{
tcpclient.Connect("localhost", 8181);
netStream = tcpclient.GetStream();
Byte[] bytes = new Byte[10000];
int readBytes = netStream.Read(bytes, 0, bytes.Length);
int Length =Int32.Parse(Encoding.ASCII.GetString(bytes, 0, readBytes));
MessageBox.Show(Length.ToString());
int i = 0;
while (i < Length)
{
i++;
Byte[] b = new Byte[10000];
readBytes = netStream.Read(bytes, 0, bytes.Length);
String response = Encoding.ASCII.GetString(b, 0, readBytes);
MessageBox.Show(response);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
You can use a StateObject to keep track of how large your data is, and then test during ReadCallback to see if you have "all" of the message. If you don't have all of your message, you call BeginRecieve again with the current StateObject.
Here is a decent example: http://www.csharphelp.com/2007/02/asynchronous-server-socket-using-c/
This is what I been using:
How to use the buffer on SocketAsyncEventArgs object
Look at the accepted answer. 1st off, this is using something call completion port which is highly efficient than async. Secondly, I find that it is very easy to troubleshoot by looking at e.SocketError to find out the exact cause for failure.
How it works is that for your message to send, append the message with a header and trailer.
So when it receive the message, it will check if the trailer is received. If trailer not received, it will continue receive for that client, and append the received message to the stringBuilder object. Once the trailer is received, just call stringbuilder.toString() to get the whole content.

Categories

Resources