Here is a sample server program written in c# which receives an id from a client. My sample code is given below. I want to send a string array to client and display is on the client console.
The sample array string can be:
string[] arr1 = new string[] { "one", "two", "three" };
What additional code I need to add with the following server and client code?
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace server
{
class Program
{
static void Main(string[] args)
{
TcpListener tcpListener = new TcpListener(IPAddress.Any, 1234);
tcpListener.Start();
while (true)
{
TcpClient tcpClient = tcpListener.AcceptTcpClient();
byte[] data = new byte[1024];
NetworkStream ns = tcpClient.GetStream();
int recv = ns.Read(data, 0, data.Length);
string id = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine(id);
}
}
}
}
Since Tcp is a stream based protocol, I would suggest you use something higher level that plain byte[]. If all you need is to send strings from client to server and vice-versa, I think a StreamReader and a StreamWriter on both ends would work great. On the StreamWriter side, you've got a WriteLine(string) method to send to the client and the StreamReader has a similar method ReadLine().
Here's a simplification that you could apply to your model:
Server side:
TcpClient client; //Let's say it's already initialized and connected properly
StreamReader reader = new StreamReader(client.GetStream());
while(client.Connected)
{
string message = reader.ReadLine(); //If the string is null, the connection has been lost.
}
Client side:
TcpClient client; //Same, it's initialized and connected
StreamWriter writer = new StreamWriter(client.GetStream());
writer.AutoFlush = true; //Either this, or you Flush manually every time you send something.
writer.WriteLine("My Message"); //Every message you want to send
StreamWriter will end every message with a new line so that the StreamReader knows when the full string has been received.
Note that a TCP connection is a full-duplex connection. Meaning you can simultaneously send and receive data. Checkout the WriteLineAsync(string) and ReadLineAsync() methods if you want to implement something like this.
If you want to send arrays, establish a simple protocol looking a bit like this:
Send the length of the string[]. Example: writer.WriteLine(myArray.Length.ToString);
Receive and parse this length
Send all strings one after the other on the server side
Receive all strings in a for loop on the client side.
Once you received all strings, repeat the process.
Sending String Array to client
TcpListener tcpListener = new TcpListener(IPAddress.Any, 1234);
tcpListener.Start();
while (true)
{
TcpClient tcpClient = tcpListener.AcceptTcpClient();
byte[] data = new byte[1024];
NetworkStream ns = tcpClient.GetStream();
string[] arr1 = new string[] { "one", "two", "three" };
var serializer = new XmlSerializer(typeof(string[]));
serializer.Serialize(tcpClient.GetStream(), arr1);
tcpClient.GetStream().Close()
tcpClient.Close();
int recv = ns.Read(data, 0, data.Length);
in this line
string id = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine(id);
}
}
Client
try
{
byte[] data = new byte[1024];
string stringData;
TcpClient tcpClient = new TcpClient("127.0.0.1", 1234);
NetworkStream ns = tcpClient.GetStream();
var serializer = new XmlSerializer(typeof(string[]));
var stringArr = (string[])serializer.Deserialize(tcpClient.GetStream());
foreach (string s in stringArr)
{
Console.WriteLine(s);
}
string input = Console.ReadLine();
ns.Write(Encoding.ASCII.GetBytes(input), 0, input.Length);
ns.Flush();
}
catch (Exception e)
{
Console.Write(e.Message);
}
Console.Read();
Related
I want to send messages between the server and the client through TcpClient. Here's my code. The client sends "HELLO" to the server, the server prints the message after receiving it, and sends "HI" to the client, the client prints the message after receiving it.
Note the code at (1) in the Client code, the program will be stuck here. If I remove this code, the program can run normally, but of course, the client cannot receive the response from the server. What's the problem and how to solve it? Thx.
Server
void Main()
{
var listener = new TcpListener(IPAddress.Any, 1234);
listener.Start();
var client = listener.AcceptTcpClient();
var rs = new StreamReader(client.GetStream());
var msg = rs.ReadLine();
Console.WriteLine($"RECEIVED: {msg}");
var ws = client.GetStream();
var data = Encoding.ASCII.GetBytes("HI");
ws.Write(data, 0, data.Length);
client.Close();
}
Client
void Main()
{
var client = new TcpClient();
client.Connect(IPAddress.Parse("127.0.0.1"), 1234);
var ws = client.GetStream();
var data = Encoding.ASCII.GetBytes("HELLO");
ws.Write(data, 0, data.Length);
var msg = "nothing";
msg = new StreamReader(client.GetStream()).ReadLine(); //(1)
Console.WriteLine($"RECEIVED: {msg}");
client.Close();
}
I have implemented a Server and Client with TcpListener and TcpClient.
Basically the server wait to a client connected to receive data and close, the client will connect, write and close too.
The problem is when I send an incomplete http request the server can't read it. For example "GET / HTTP/1.1\r\n" is incomplete because it must end with '\r\n' twice, but if i send "PET / HTTP/1.1\r\n" (is not an http request) the server read it fine. What's happened there?
This is my example code:
static void Main()
{
var message = #"GET / HTTP/1.1
";
var encodingMessage = message.Select(Convert.ToByte).ToArray();
// SERVER
var serverThread = new Thread(() =>
{
var tcpListener = new TcpListener(IPAddress.Parse("172.20.48.37"), 23000);
tcpListener.Start();
var tcpClient = tcpListener.AcceptTcpClient();
var networkStream = tcpClient.GetStream();
var buffer = new byte[250];
var bytesCount = networkStream.Read(buffer, 0, buffer.Length);
Console.WriteLine(#"received bytes: {0}", bytesCount); // print the received bytes
networkStream.Close();
networkStream.Dispose();
tcpClient.Close();
tcpListener.Stop();
});
serverThread.Start();
Thread.Sleep(3000);
// CLIENT
var client = new TcpClient();
client.Connect(new IPEndPoint(IPAddress.Parse("172.20.48.37"), 23000));
var stream = client.GetStream();
stream.Write(encodingMessage, 0, encodingMessage.Length);
stream.Close();
stream.Dispose();
client.Close();
}
TcpListener tcpServer = new TcpListener(8080);
tcpServer.Start();
tcpServer.BeginAcceptTcpClient(new AsyncCallback(this.messageRecived), tcpServer);
I have some code for accept reading from tcp client, client send massage in this way:
TcpClient client = new TcpClient("192.168.0.2", 8080)
string Str = "it's work";
byte[] Buffer = Encoding.ASCII.GetBytes(Str);
client.GetStream().Write(Buffer, 0, Buffer.Length);
the problem is in messageRecived method:
public void messageRecived(IAsyncResult result)
{
byte[] data = new byte[20000];
string outData;
TcpListener server = (TcpListener)result.AsyncState;
server.AcceptTcpClient().GetStream().Read(data, 0, server.Server.ReceiveBufferSize);
outData = Encoding.ASCII.GetString(data);
addLog(outData);
}
When i send message to server the method received run until to this line:
server.AcceptTcpClient().GetStream().Read(data, 0, server.Server.ReceiveBufferSize);
and in the next iteration it begin from next line to the end of method. What is the problem?
probably because you are not closing stream from client, please refer to below link to properly dispose stream from client
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.getstream(v=vs.110).aspx
Try to flush the client Stream.
TcpClient client = new TcpClient("192.168.0.2", 8080)
string Str = "it's work";
byte[] Buffer = Encoding.ASCII.GetBytes(Str);
var stream = client.GetStream()
stream.Write(Buffer, 0, Buffer.Length);
stream.Flush()
I am working on a C# and android client/server application.
Android is sending a message to C# and I can see it is sending the correct data, however C# doesn't receive all of it.
Below is the code I have in C#
TcpListener tcpListener = new TcpListener(IPAddress.Any, serverTCPPort);
tcpListener.Start();
while (true)
{
tcpClient = tcpListener.AcceptTcpClient();
stream = tcpClient.GetStream();
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
writer.NewLine = "\r\n";
writer.AutoFlush = true;
byte[] serverData = new byte[tcpClient.ReceiveBufferSize];
int length = stream.Read(serverData, 0, serverData.Length);
string received = Encoding.ASCII.GetString(serverData, 0, length);
}
Below is how I am sending the data via Android
i
f (contactInformation.photoBase64String != null) {
bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), Uri.parse(contactInformation.photoBase64String));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
bitmap64Encoded = Base64.encodeToString(b, Base64.DEFAULT);
}
Toast.makeText(context, "Incoming call from " + contactInformation.contactName, Toast.LENGTH_LONG).show();
XmlSettings xmlSettings = new XmlSettings();
xmlSettings.setIndent(true);
XmlWriter xmlWriter = new XmlWriter(xmlSettings);
xmlWriter.writeStartDocument();
xmlWriter.writeStartElement("StatusManager");
xmlWriter.writeElementString("Command", Defines.ServerCommands.IncomingCall.toString());
xmlWriter.writeStartElement("CallInformation");
xmlWriter.writeElementString("PhoneNumber", phoneNumber);
xmlWriter.writeElementString("ContactName", contactInformation.contactName);
if (contactInformation.photoBase64String != null)
{
xmlWriter.writeElementString("PhotoUri", bitmap64Encoded);
}
xmlWriter.writeEndElement();
xmlWriter.writeEndElement();
String xml = xmlWriter.returnXmlOutput();
TCPSender tcpSender = new TCPSender(context, DeviceManagement.servers.get(0), xmlWriter.returnXmlOutput());
Thread thread = new Thread(tcpSender);
thread.start();
The TCP Sender is
#Override
public void run() {
Log.d("TCPSender", xml);
HelperClass helperClass = new HelperClass();
try
{
Socket socket = new Socket(foundServerInformation.ipAddress, foundServerInformation.tcpServerPort);
OutputStream out = socket.getOutputStream();
PrintWriter output = new PrintWriter(out);
output.println(xml);
output.flush();
I guess the data is too big for the byte array but I can't find a way of how to ensure I get all of the information that Android is sending.
It's difficult to know where the problem might be (I see your code is OK), but here you have a working example from Microsoft how it should be done, maybe it gives you some clues.
TcpListener server=null;
try
{
// Set the TcpListener on port 13000.
Int32 port = 13000;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);
// Start listening for client requests.
server.Start();
// Buffer for reading data
Byte[] bytes = new Byte[256];
String data = null;
// Enter the listening loop.
while(true)
{
Console.Write("Waiting for a connection... ");
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
data = null;
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream();
int i;
// Loop to receive all the data sent by the client.
while((i = stream.Read(bytes, 0, bytes.Length))!=0)
{
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
// Process the data sent by the client.
data = data.ToUpper();
byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
// Send back a response.
stream.Write(msg, 0, msg.Length);
Console.WriteLine("Sent: {0}", data);
}
// Shutdown and end connection
client.Close();
}
}
catch(SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
finally
{
// Stop listening for new clients.
server.Stop();
}
Console.WriteLine("\nHit enter to continue...");
Console.Read();
I've finally managed to get it working, it was something to do with using the SendReceiveBuffer which I did try but didn't work but now it does so I guess I missed something.
Below is the code I am using to receive all of the data
TcpListener tcpListener = new TcpListener(IPAddress.Any, serverTCPPort);
tcpListener.Start();
string received = "";
while (true)
{
tcpClient = tcpListener.AcceptTcpClient();
stream = tcpClient.GetStream();
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
writer.NewLine = "\r\n";
writer.AutoFlush = true;
byte[] bytes = new byte[tcpClient.SendBufferSize];
int recv = 0;
while (true)
{
recv = stream.Read(bytes, 0, tcpClient.SendBufferSize);
received += System.Text.Encoding.ASCII.GetString(bytes, 0, recv);
if (received.EndsWith("\n\n"))
{
break;
}
}
}
I'm sending an object (class name House) over TCP using the TcpListener on the server side in response to any message received from the TcpClient.
When the message is received, it is currently populating a text box named textBox1.
If I send a line of text, it works fine. You'll notice that I have a redundant line "Hello, I'm a server" for testing this purpose. But when I send the XML, it is cutting it off prematurely.
When I send serialised XML in to the stream, I'm also receiving this error from the server side:
Unable to read data from the transport connection: An existing
connection was forcibly closed by the remote host.
Here's my server code
// Set the variables for the TCP listener
Int32 port = 14000;
IPAddress ipaddress = IPAddress.Parse("132.147.160.198");
TcpListener houseServer = null;
// Create IPEndpoint for connection
IPEndPoint ipend = new IPEndPoint(ipaddress, port);
// Set the server parameters
houseServer = new TcpListener(port);
// Start listening for clients connecting
houseServer.Start();
// Buffer for reading the data received from the client
Byte[] bytes = new Byte[256];
String data = "hello, this is a house";
// Show that the TCP Listener has been initialised
Console.WriteLine("We have a TCP Listener, waiting for a connection...");
// Continuing loop looking for
while (true)
{
// Create a house to send
House houseToSendToClient = new House
{
house_id = 1,
house_number = 13,
street = "Barton Grange",
house_town = "Lancaster",
postcode = "LA1 2BP"
};
// Get the object serialised
var xmlSerializer = new XmlSerializer(typeof(House));
using (var memoryStream = new MemoryStream())
{
xmlSerializer.Serialize(memoryStream, houseToSendToClient);
}
// Accept an incoming request from the client
TcpClient client = houseServer.AcceptTcpClient();
// Show that there is a client connected
//Console.WriteLine("Client connected!");
// Get the message that was sent by the server
NetworkStream stream = client.GetStream();
// Blank int
int i;
// Loop for receiving the connection from the client
// >>> ERROR IS ON THIS LINE <<<
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
Console.WriteLine("here");
// Take bytes and convert to ASCII string
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received s, return house");
// Convert the string to a byte array, ready for sending
Byte[] dataToSend = System.Text.Encoding.ASCII.GetBytes("Hello, I'm a server");
// Send the data back to the client
//stream.Write(dataToSend, 0, dataToSend.Length);
// Send serialised XML in to the stream
xmlSerializer.Serialize(stream, houseToSendToClient);
}
// Close the connection
client.Close();
}
Client code
// Get the object serialised
var xmlSerializer = new XmlSerializer(typeof(House));
// Set the variables for the TCP client
Int32 port = 14000;
IPAddress ipaddress = IPAddress.Parse("127.0.0.1");
IPEndPoint ipend = new IPEndPoint(ipaddress, port);
string message = "s";
try
{
// Create TCPCLient
//TcpClient client = new TcpClient("localhost", port);
TcpClient client = new TcpClient();
// Convert the string to a byte array, ready for sending
Byte[] dataToSend = System.Text.Encoding.ASCII.GetBytes(message);
// Connect using TcpClient
client.Connect(ipaddress, port);
// Client stream for reading and writing to server
NetworkStream stream = client.GetStream();
// Send the data to the TCP Server
stream.Write(dataToSend, 0, dataToSend.Length);
//xmlSerializer.Serialize(stream, houseToSend);
// Buffer to store response
Byte[] responseBytes = new Byte[256];
string responseData = String.Empty;
// Read the response back from the server
Int32 bytes = stream.Read(responseBytes, 0, responseBytes.Length);
responseData = System.Text.Encoding.ASCII.GetString(responseBytes, 0, bytes);
textBox1.Text = responseData;
// Close the stream and the client connection
stream.Close();
client.Close();
}
catch (SocketException e)
{
MessageBox.Show(e.ToString());
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
I've marked on the code where the error is appearing.
Is it because the message is too long?
Your client code is assuming that the entire message will come through in one call to the Read(...) method, which is absolutely wrong. From the MSDN docs: "An implementation is free to return fewer bytes than requested even if the end of the stream has not been reached."
It's possible that, for a 1024-byte XML document, you may have to call Read(...) 1024 times to get the entire message.
Really, you'd do well to send a four-byte length before you send the XML, so that the client knows how much data to expect. The client will read four bytes, convert that to an integer length, then read that many more bytes, then turn those bytes into XML.