Send and Receive TCP socket android client - c#

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.

Related

Framing bytes (Begining and End) to be added inside the TCP/IP protocol on the client request

I am writing TCP/IP Client using C# - System.Net.Sockets to call the Interface created in the TCP/IP Socket on the 'X' Server.
Message body text format - 20 digits(ASCII format)
All messages text will be framed with below format,
Framing bytes - 2 digit Hexadecimal values
Needs to be add in the starting and ending fields
It needs to be in the TCP/IP protocol and not within the body of the message.
Question: How do I add hexadecimal framing bytes in the TCP/IP protocol and not within the body of message.
Here is my code snippet -
public static void Connect()
{
// Create a TcpClient.
// Note, for this client to work you need to have a TcpServer
// connected to the same address as specified by the server, port
// combination.
Int32 port = 1234;
String server = "serverip";
String message = "12345678901234567890"
TcpClient client = new TcpClient(server, port);
// Translate the passed message into ASCII and store it as a Byte array.
Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
// Get a client stream for reading and writing.
// Stream stream = client.GetStream();
NetworkStream stream = client.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}", message);
// Receive the TcpServer.response.
// Buffer to store the response bytes.
data = new Byte[256];
// String to store the response ASCII representation.
String responseData = String.Empty;
// Read the first batch of the TcpServer response bytes.
Int32 bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}", responseData);
// Close everything.
stream.Close();
client.Close();
Console.WriteLine("\n Press Enter to continue...");
Console.Read();
}
Framing bytes (you dont say what they contain, it looks like you are quoting from a spec) seem to be needed to be added before and after the message, just send them. Assumed that the before bytes are 0x1234
var pre = new Byte[2];
pre[0] = 0x12;
pre[1] = 0x34;
stream.Write(pre, 0, 2);
then after the body of the message send the trailer the same way

Networking between Indy10 and System.Net.Sockets

Me and my partner working on a project where my partner is developing in Pascal and using Indy10 socket for networking and I'm developing under C# in an UWP project. Therefore for networking I have to use streamsocket namespace.
The problem is, that my partner uses ReadStream method with -1 and false parameters, that mean that the length of the receiving stream is indetermined. Therefore, I have to send a length prefix calculated (in this case I use BitConverter.GetBytes method) from the data in my stream (for example using DataWriter class) continued with the data itself.
But Indy10 socket don't receives nothing. It looks like it stucks on waiting for the packet or I don't know.
Does anybody hit that problem? Please help, we've been looking after the solution for about two weeks. I had read all the similar questions here in StackOverflow, a blog about the use of framing, delimitering. Searched for solution in Indy Socket source code itself.
Please help!
UPDATE 1
C# code. In this case I am sending from a WPF application. The logic, how streams are used in UWP are almost the same, just using StreamSocket and DataWriter.
TcpClient client = new TcpClient(hostTextBox.Text, int.Parse(portTextBox.Text));
Byte[] byteMessage = Encoding.Unicode.GetBytes(messageTextBox.Text);
Byte[] lenghtPrefix = BitConverter.GetBytes(byteMessage.Length);
Byte[] concatedData = new byte[lenghtPrefix.Length + byteMessage.Length];
lenghtPrefix.CopyTo(concatedData, 0);
byteMessage.CopyTo(concatedData, lenghtPrefix.Length);
NetworkStream stream = client.GetStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(concatedData);
writer.Flush();
stream.Close();
client.Close();
But we have tried this solution too:
Byte[] byteMessage = Encoding.Unicode.GetBytes(messageTextBox.Text);
Byte[] lenghtPrefix = BitConverter.GetBytes(byteMessage.Length);
Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
socket.Connect(hostTextBox.Text, int.Parse(portTextBox.Text));
socket.Send(lenghtPrefix, SocketFlags.None);
socket.SendBufferSize = byteMessage.Length;
socket.Send(byteMessage, SocketFlags.None);
socket.Close();
Pascal code on the server side, waiting for stream. It is crucial to receive in this way, because the software's other modules (also written in Pascal using Indy10) communicating with the server in this way.
function Receive(const AContext: TIdContext): string;
var
Stream: TMemoryStream;
begin
try
Result := '';
Stream := TMemoryStream.Create;
if AContext.Connection.Connected then
AContext.Connection.IOHandler.ReadStream(Stream, -1, False);
finally
Result := UnPackStream(Stream);
Stream.Free;
end;
end;
Finally, here is the solution. We worked on that all day. We used Synapse socket as a reference. In the end here is the code under UWP, and we tested it in other desktop projects (WPF, Winforms) too (with TcpClient and NetworkStream).
BitConverter and prefixing the hole stream with a number didn't worked, because Indy waits for the length in binary format, therefore the byte array have to contain values representing the binary length. I hope it will help others having similar problem!
Windows.Networking.Sockets.StreamSocket socket = new Windows.Networking.Sockets.StreamSocket();
Windows.Networking.HostName serverHost = new Windows.Networking.HostName(hostTextBox.Text);
string serverPort = portTextBox.Text;
await socket.ConnectAsync(serverHost, serverPort);
//Write data to the server.
DataWriter writer = new DataWriter(socket.OutputStream);
byte[] data = Encoding.Unicode.GetBytes(messageTextBox.Text);
byte[] size = new byte[4];
ushort x = (ushort)(data.Length >> 16);
ushort y = (ushort)(data.Length);
size[0] = (byte)(x / 256);
size[1] = (byte)(x % 256);
size[2] = (byte)(y / 256);
size[3] = (byte)(y % 256);
writer.WriteBytes(size);
writer.WriteBytes(data);
await writer.StoreAsync();
await writer.FlushAsync();
writer.DetachStream();
//Read response.
var bytes = new byte[4];
DataReader reader = new DataReader(socket.InputStream);
await reader.LoadAsync(4);
reader.ReadBytes(bytes);
int length = bytes[0] * 256 * 256 * 256 + bytes[1] * 256 * 256 + bytes[2] * 256 + bytes[3];
byte[] dat = new byte[length];
var count = await reader.LoadAsync((uint)length);
reader.ReadBytes(dat);
responseTextBlock.Text = Encoding.Unicode.GetString(dat);
reader.DetachStream();
socket.Dispose();
When calling TIdIOHandler.ReadStream() in Indy, if AByteCount is -1 and AReadUntilDisconnect is False, ReadStream() will read the first 4 bytes (Int32) or 8 bytes (Int64) (depending on the value of the TIdIOHandler.LargeStream property) and interpret them as an integer in network byte order (big-endian), then read the number of bytes specified by that integer (if greater than 0).
The main problem with your first C# example is that you are using a StreamWriter, which is designed for sending text, not binary data. If you try to write a Byte[] array with a StreamWriter, it will not be sent as-is, it will be formatted to a textual representation that is not compatible with Indy. You don't need the StreamWriter, you can use the NetworkStream as-is, it has a Write() method for Byte[] data. Or use a BinaryWriter.
Another problem with both C# examples is that you are using BitConverter without taking endian into account. Its GetBytes(Int32) method creates an array of bytes in the same endian as the calling machine's architecture. Windows is primarily a little-endian environment, but ReadStream() is expecting the integer bytes in big-endian.
Try something more like this:
TcpClient client = new TcpClient(hostTextBox.Text, int.Parse(portTextBox.Text));
Byte[] byteMessage = Encoding.Unicode.GetBytes(messageTextBox.Text);
Byte[] lengthPrefix = BitConverter.GetBytes(byteMessage.Length);
if (BitConverter.IsLittleEndian)
Array.Reverse(lengthPrefix);
NetworkStream stream = client.GetStream();
stream.Write(lengthPrefix, 0, lengthPrefix.Length);
stream.Write(byteMessage, 0, byteMessage.Length);
stream.Close();
client.Close();
Or this:
TcpClient client = new TcpClient(hostTextBox.Text, int.Parse(portTextBox.Text));
Byte[] byteMessage = Encoding.Unicode.GetBytes(messageTextBox.Text);
Byte[] lengthPrefix = BitConverter.GetBytes(byteMessage.Length);
if (BitConverter.IsLittleEndian)
Array.Reverse(lengthPrefix);
NetworkStream stream = client.GetStream();
BinaryWriter writer = new BinaryWriter(stream);
// BinaryWriter.Write(Int32) writes in little-endian only,
// so you still need to use Write(Byte[]) for the length value...
writer.Write(lengthPrefix);
writer.Write(byteMessage)
writer.Flush();
stream.Close();
client.Close();

Socket writing not working properly 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?

Sending and receiving an image file C#

I have been struggling for a while now to send an image file over sockets. I believe I am very close, but I haven't gotten it yet. I am trying to send the image from the server to the client.
Here is my server code:
//Init listener
listener = new TcpListener(new IPEndPoint(IPAddress.Any, 550));
//Start listening for connections
listener.Start();
Console.WriteLine("Waiting for connection");
s = listener.AcceptSocket();
//If we reach here, we have a connection
Console.WriteLine("Connected");
//Get the screenshot and apply it to our memory stream
img = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);
imgG = Graphics.FromImage(img);
imgG.CopyFromScreen(0, 0, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);
ms = new MemoryStream();
img.Save(ms, ImageFormat.Jpeg);
img.Save("sc.jpg", ImageFormat.Jpeg);
//Convert image to byte array, and then send it
byte[] byteArray = ms.ToArray();
s.Send(byteArray);
s.Close();
Console.Read();
Here is my client code:
client = new TcpClient();
client.Connect(new IPEndPoint(IPAddress.Parse(IPBox.Text), 550));
s = client.Client;
buffer = new byte[100000];
s.Receive(buffer);
ms.Read(buffer, 0, 100000);
img = (Bitmap)Image.FromStream(ms);
imgContainer.Image = (Image)img;
I think I am very close, but I might be far off. I am new to networking, and require help please. Thanks A lot.
The problem is that in your client, you are assuming that you received 100000 bytes from the server, and you're putting all 100000 bytes into the memory stream.
There is a great sample on the MSDN page for TcpClient which shows receiving from a TcpClient by using the underlying NetworkStream. Also, you will want to keep track of how many bytes you actually received (this is the return value from the NetworkStream.Read function). Finally, you'll want to keep reading until there is no more data to be read from the host. If your image is larger than your buffer, then you'll only have a partial image also. The sample on the linked page for NetworkStream.Read shows continually reading from the stream while there is data available.

Socket.send() hanging/sleeping in server

I have this method which i use to send a Transfer object
IPEndPoint ipEnd = new IPEndPoint(IPAddress.Any, 7777);
Socket sockListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
sockListener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
sockListener.Bind(ipEnd);
sockListener.Listen(100);
s = sockListener.Accept();
private void sendToClient(Transfer.Transfer tt)
{
byte[] buffer = new byte[15000];
IFormatter f = new BinaryFormatter();
Stream stream = new MemoryStream(buffer);
f.Serialize(stream, tt);
Console.WriteLine("1/3 serialized");
stream.Flush();
Console.WriteLine("2/3 flushed stream");
s.Send(buffer, buffer.Length, 0);
Console.WriteLine("3/3 send to client");
}
The strange thing is it work the first 2 times i call it, then on the 3rd call it hangs on s.send().
Its the same if i want to send String instead of Transfer.
The comment by #nos is probably correct, the TCP Send buffer is probably filling up and the 3rd call to s.send() is blocking until the data is sent over the network. You can set the used buffer sizes like this:
Socket s = sockListener.Accept();
s.ReceiveBufferSize = 1024 * 64;
s.SendBufferSize = 1024 * 64;
You should be able to confirm your problem by setting your buffer sizes to a larger multiple of the size of data you're sending.
Also, as suggested, you should check the client to make sure its reading the data properly.

Categories

Resources