Reading data from a TCP Socket not getting all of the data - c#

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;
}
}
}

Related

TCP how do I relay the packets from my client to the server

So I am working on creating my own proxy server for my game server.
Whats happening so far is that I try to connect to my Terraria server and it says
Connecting..
Then I start my server application which accepts incoming requests on that specific IP & port and it prompts a MessageBox saying"Connected" and then the game goes from "Connecting..." to "Connecting to server..." but it gets stuck there, this is most likely because I am not redirecting the traffic from my proxy server to my server.. Right?
I've been trying to .Write() to the stream but I think I am writing to the wrong stream, do I write to the stream that accepts connections or do I create a new stream for outgoing traffic?
public partial class MainWindow : Window
{
public static IPAddress remoteAddress = IPAddress.Parse("127.0.0.1");
public TcpListener remoteServer = new TcpListener(remoteAddress, 7777);
public TcpClient client = default(TcpClient);
public TcpClient RemoteClient = new TcpClient("terraria.novux.ru", 7777);
public MainWindow()
{
InitializeComponent();
}
private void BtnListen_OnClick(object sender, RoutedEventArgs e)
{
if (StartServer())
{
client = remoteServer.AcceptTcpClient();
MessageBox.Show("Connected");
var receivedBuffer = new byte[1024];
//Should I write to this one instead?
var clientStream = client.GetStream();
var stream = RemoteClient.GetStream();
while (client.Connected)
if (client.Connected)
if (client.ReceiveBufferSize > 0)
{
receivedBuffer = new byte[1024];
stream.Write(receivedBuffer, 0, receivedBuffer.Length);
}
}
}
private bool StartServer()
{
try
{
remoteServer.Start();
MessageBox.Show("Server Started...");
return true;
}
catch (Exception exception)
{
MessageBox.Show(exception.ToString());
throw;
}
}
}
A simplified implementation could look like this.
public class Program
{
public static void Main(string[] args)
{
StartTcpListener("localhost", 9000);
}
private static byte[] SendReceiveRemoteServer(string host, int port, byte[] data)
{
try
{
// 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.
var client = new TcpClient(host, port);
// Get a client stream for reading and writing.
// Stream stream = client.GetStream();
var stream = client.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent to server: {0}", Encoding.ASCII.GetString(data));
// Receive the TcpServer.response.
// Read the first batch of the TcpServer response bytes.
var bytes = new byte[256];
var allBytes = new List<byte>();
var i = stream.Read(bytes, 0, bytes.Length);
// Loop to receive all the data sent by the client.
while (i != 0)
{
allBytes.AddRange(bytes);
bytes = new Byte[256];
i = stream.DataAvailable ? stream.Read(bytes, 0, bytes.Length) : 0;
}
Console.WriteLine("Received from server: {0}", Encoding.ASCII.GetString(data));
// Close everything.
stream.Close();
client.Close();
return allBytes.ToArray();
}
catch (ArgumentNullException e)
{
Console.WriteLine("ArgumentNullException: {0}", e);
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
Console.WriteLine("\n Press Enter to continue...");
return new byte[0];
}
private static void StartTcpListener(string host, int port)
{
TcpListener server = null;
try
{
var ipHostInfo = Dns.GetHostEntry(host);
var ipAddress = ipHostInfo.AddressList[0];
// TcpListener server = new TcpListener(port);
server = new TcpListener(ipAddress, port);
// Start listening for client requests.
server.Start();
// Enter the listening loop.
while (true)
{
Console.WriteLine("Waiting for a connection... ");
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
var client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
// Get a stream object for reading and writing
var stream = client.GetStream();
// Buffer for reading data
var bytes = new Byte[256];
var allBytes = new List<byte>();
var i = stream.Read(bytes, 0, bytes.Length);
// Loop to receive all the data sent by the client.
while (i != 0)
{
allBytes.AddRange(bytes);
bytes = new Byte[256];
i = stream.DataAvailable ? stream.Read(bytes, 0, bytes.Length) : 0;
}
if (allBytes.Count > 0)
{
Console.WriteLine("Received from client: {0}", Encoding.ASCII.GetString(allBytes.ToArray()));
var received = SendReceiveRemoteServer("localhost", 11000, allBytes.ToArray());
// Send back a response.
stream.Write(received, 0, received.Length);
Console.WriteLine("Sent to client: {0}", Encoding.ASCII.GetString(received));
}
// 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...");
}
}
Although improvements should be made:
make it async
make it work with multiple TcpClients at the same time

TCPlistener server-client and client-server ( send message to client from server)

All i want to do is send message to client from server. I try a lot of tutorial etc. but still can't send message from server to client.
Send from client to server is simple and have it in code. When client Send "HI" to server i want to respond Hi to client. But dunno what should i add to my code. Can someone help me with that? Please don't do it like duplicate i know there is a lot of similar topic but can't find solution.
Server code:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
IPAddress ip = Dns.GetHostEntry("localhost").AddressList[0];
TcpListener server = new TcpListener(ip, Convert.ToInt32(8555));
TcpClient client = default(TcpClient);
try
{
server.Start();
Console.WriteLine("Server started...");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
};
while (true)
{
client = server.AcceptTcpClient();
byte[] receivetBuffer = new byte[100];
NetworkStream stream = client.GetStream();
stream.Read(receivetBuffer, 0, receivetBuffer.Length);
StringBuilder msg = new StringBuilder();
foreach(byte b in receivetBuffer)
{
if (b.Equals(59))
{
break;
}
else
{
msg.Append(Convert.ToChar(b).ToString());
}
}
////Resive message :
if (msg.ToString() =="HI")
{
///#EDIT 1
///// HERE Is SENDING MESSAGE TO CLIENT//////////
int byteCount = Encoding.ASCII.GetByteCount("You said HI" + 1);
byte[] sendData = new byte[byteCount];
sendData = Encoding.ASCII.GetBytes("You said HI" + ";");
stream.Write(sendData, 0, sendData.Length);
}
}
Client code:
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
try
{
string serverIP = "localhost";
int port = Convert.ToInt32(8555);
TcpClient client = new TcpClient(serverIP, port);
int byteCount = Encoding.ASCII.GetByteCount("HI"+ 1);
byte[] sendData = new byte[byteCount];
sendData = Encoding.ASCII.GetBytes("HI" + ";");
NetworkStream stream = client.GetStream();
stream.Write(sendData, 0, sendData.Length);
///////////////////////////////HERE I WANT A read message from server/
/////////////////////////////////////////////////////////////////////
stream.Close();
client.Close();
}
catch(Exception ex)
{
ex.ToString();
}
}
Try this Here is my version of client and server ,feel free to ask if any reference problem ,the client wait for server to (online) then if server is online connect with it.
Method to Connect with Server
private void Connectwithserver(ref TcpClient client)
{
try
{
//this is server ip and server listen port
server = new TcpClient("192.168.100.7", 8080);
}
catch (SocketException ex)
{
//exceptionsobj.WriteException(ex);
Thread.Sleep(TimeSpan.FromSeconds(10));
RunBoTClient();
}
}
byte[] data = new byte[1024];
string stringData;
TcpClient client;
private void RunClient()
{
NetworkStream ns;
Connectwithserver(ref client);
while (true)
{
ns = client.GetStream();
//old
// ns.ReadTimeout = 50000;
//old
ns.ReadTimeout = 50000;
ns.WriteTimeout = 50000;
int recv = default(int);
try
{
recv = ns.Read(data, 0, data.Length);
}
catch (Exception ex)
{
//exceptionsobj.WriteException(ex);
Thread.Sleep(TimeSpan.FromSeconds(10));
//try to reconnect if server not respond
RunClient();
}
//READ SERVER RESPONSE/MESSAGE
stringData = Encoding.ASCII.GetString(data, 0, recv);
}
}
Server
IPAddress localAdd = IPAddress.Parse(SERVER_IP);
TcpListener listener = new TcpListener(localAdd, PORT_NO);
Console.WriteLine("Listening...");
listener.Start();
while (true)
{
//---incoming client connected---
TcpClient client = listener.AcceptTcpClient();
//---get the incoming data through a network stream---
NetworkStream nwStream = client.GetStream();
byte[] buffer = new byte[client.ReceiveBufferSize];
//---read incoming stream---
int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize);
//---convert the data received into a string---
string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine("Received : " + dataReceived);
//IF YOU WANT TO WRITE BACK TO CLIENT USE
string yourmessage = console.ReadLine();
Byte[] sendBytes = Encoding.ASCII.GetBytes(yourmessage);
//---write back the text to the client---
Console.WriteLine("Sending back : " + yourmessage );
nwStream.Write(sendBytes, 0, sendBytes.Length);
client.Close();
}
listener.Stop();

C# Reading stream from TcpClient

I'm making a server - client program using TcpClient and server.
To send from the server I use:
static void send(string data)
{
sw.WriteLine(data + Environment.NewLine);
}
And when the client connects I'm sending some text:
client = listener.AcceptTcpClient();
sr = new StreamReader(client.GetStream());
sw = new StreamWriter(client.GetStream());
string line;
try
{
send("Hello world");
} //More code
And to read from client:
string data;
data = sr.ReadLine();
if(data != string.Empty || data != null)
{
MessageBox.Show(data);
}
I tried putting inside while(true) and it froze, I tried putting inside a timer tick loop and it froze...
How do I fix this?
P.S: The client and the server are 2 different projects.
I believe you need something like this:
try
{
listen = new TcpListener(myAddress, port);
listen.Start();
Byte[] bytes;
while (true)
{
TcpClient client = listen.AcceptTcpClient();
NetworkStream ns = client.GetStream();
if(client.ReceiveBufferSize > 0){
bytes = new byte[client.ReceiveBufferSize];
ns.Read(bytes, 0, client.ReceiveBufferSize);
string msg = Encoding.ASCII.GetString(bytes); //the message incoming
MessageBox.Show(msg);
}
}
}
catch(Exception e)
{
//e
}
Then have this code as a background thread:
Thread thread = new Thread(the functions name);
thread.IsBackground = true;
thread.Start();
I hope I understand what you need.
Try this one, grandpa's way.
int i = 0;
while (stream.DataAvailable == true)
{
bytes[i] = ((byte)stream.ReadByte());
i++;
}
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);

Proxy server does not load images

I'm trying to make a proxy server with C#.
Here's my code:
static void Main(string[] args)
{
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;
WebRequest request;
WebResponse response;
// 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;
String[] input;
// Loop to receive all the data sent by the client.
while (stream.DataAvailable)
{
data = null;
i = stream.Read(bytes, 0, bytes.Length);
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine(String.Format("Received: {0}", data));
input = data.Split();
Console.WriteLine("\n\r\n input[1]" + input[1] + "\n");
Stream dataStream;
StreamReader reader;
string responseFromServer;
try
{
request = WebRequest.Create(input[1]);
response = request.GetResponse();
// Process the data sent by the client.
data = data.ToUpper();
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
reader = new StreamReader(dataStream);
// Read the content.
responseFromServer = reader.ReadToEnd();
// Display the content
Console.WriteLine(responseFromServer);
// Clean up the streams and the response.
byte[] msg = System.Text.Encoding.ASCII.GetBytes(responseFromServer);
// Send back a response.
stream.Write(msg, 0, msg.Length);
// Console.WriteLine("Sent: {0}", data);
//stream.Write();
reader.Close();
response.Close();
}
catch (System.UriFormatException e)
{
Console.WriteLine("Exception due to" + e.Data);
Console.WriteLine("Input[1] = " + input[1]);
}
data = null;
}
// 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();
}
It does not work for ssl requests but seems to work for http.
However, it does not load any images.
I'm using Firefox as the browser.
Any ideas why?
Also is this the best way to make a proxy server? Are there any other methods?
After a bit of testing, I wrote my own code.
using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Text;
namespace SharpProxy
{
class MainClass
{
private static void StartAcceptingClient(IAsyncResult ar)
{
var tcpClient = server.EndAcceptTcpClient(ar);
server.BeginAcceptTcpClient(new AsyncCallback(StartAcceptingClient), null);
// Read the data stream from the client.
NetworkStream stream = tcpClient.GetStream();
byte[] buffer = new byte[256];
Console.WriteLine("====== GOT A NEW TCP CLIENT ====== " + tcpClient.Client.RemoteEndPoint.ToString());
int read = stream.Read(buffer, 0, 1);
MemoryStream saved = new MemoryStream();
saved.Write(buffer, 0, read);
bool isValid = false;
while (read > 0 )
{
read = stream.Read(buffer, 0, 1);
saved.Write(buffer, 0, read);
//Check if the last four bytes were a double \r\n.
var aBytes = saved.ToArray();
int len = aBytes.Length;
if (aBytes.Length >= 4 && aBytes[len - 1] == '\n' && aBytes[len - 2] == '\r' && aBytes[len - 3] == '\n' && aBytes[len - 4] == '\r')
{
isValid = true;
break;
}
}
Console.WriteLine("End of receive.");
string originalRequest = Encoding.ASCII.GetString(saved.ToArray());
byte[] origBytes = saved.ToArray();
saved.Close();
Console.WriteLine(originalRequest);
if (!isValid)
{
Console.WriteLine("This wasn't a valid request");
return;
}
//Find the hoster and do our own request.
string host = originalRequest.Split(new char[] { '\n' }).First(line => line.StartsWith("Host:"));
host = host.Substring(5).Trim(); //Cut of rest.
Console.WriteLine("The host is: " + host);
//Do our own request.
try
{
Socket sProxy = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sProxy.Connect(host, 80);
sProxy.Send(origBytes);
//Now route everything between the tcpclient and this socket...
//create the state object
var state = new ProxyState() { ourSocket = sProxy, incomingClient = stream };
sProxy.BeginReceive(state.ReceiveBuffer, 0, state.ReceiveBuffer.Length, SocketFlags.None, new AsyncCallback(Receiver), state);
stream.BeginRead(state.SendBuffer, 0, state.SendBuffer.Length, new AsyncCallback(SendToHTTPServer), state);
}
catch (Exception) { Console.WriteLine("Exception while doing our own request"); }
}
static TcpListener server = null;
public static void Main(string[] args)
{
try
{
// Set the TcpListener on port 13000.
Int32 port = 13000;
IPAddress localAddr = IPAddress.Parse("0.0.0.0");
// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);
// Start listening for client requests.
server.Start();
Console.WriteLine("Server started on " + server.LocalEndpoint.ToString());
server.BeginAcceptTcpClient(new AsyncCallback(StartAcceptingClient), null);
while (true)
Thread.Sleep(10);
}
catch (Exception) { Console.WriteLine("Setting up the server failed"); }
}
private static void SendToHTTPServer(IAsyncResult ar)
{
try
{
ProxyState back = (ProxyState)ar.AsyncState;
int rec = back.incomingClient.EndRead(ar);
//Push this content to the server
back.ourSocket.Send(back.SendBuffer.Take(rec).ToArray());
back.incomingClient.BeginRead(back.SendBuffer, 0, back.SendBuffer.Length, new AsyncCallback(SendToHTTPServer), back);
}
catch (Exception e) { Console.WriteLine("Exc. when sending to server: " + e.ToString()); }
}
static void Receiver(IAsyncResult state)
{
try
{
ProxyState back = (ProxyState)state.AsyncState;
int rec = back.ourSocket.EndReceive(state);
//Set up the back and forth connections
back.incomingClient.Write(back.ReceiveBuffer, 0, rec);
back.ourSocket.BeginReceive(back.ReceiveBuffer, 0, back.ReceiveBuffer.Length, SocketFlags.None, new AsyncCallback(Receiver), back);
}
catch (Exception e) { Console.WriteLine("Exc. when receiving from client: " + e.ToString()); }
}
//Every proxy connection has an end an and a beginning, plus a
//Sending buffer and a receive buffer
class ProxyState
{
public NetworkStream incomingClient { get; set; }
public Socket ourSocket { get; set; }
private byte[] buffReceive = new byte[512];
private byte[] buffSend = new byte[512];
public byte[] ReceiveBuffer { get { return buffReceive; } set { buffReceive = value; } }
public byte[] SendBuffer { get { return buffSend; } set { buffSend = value; } }
}
}
}
Here's how it works: I listen on a port, and wait for a HTTP request. This is ended by a double carriage return and a linefeed, a \r\n\r\n. As soon as that happens, I try to parse the original host from the request with a Linq statement. I open my own socket to the server, and make use of the asynchronous callbacks. Basically, you need to write everything that comes from the proxy-iniator to the HTTP-Server, and everything that the HTTP-Server sends back needs to be pushed back to the original client aswell. This is why I set up my own state-object, which just saves the incomming client and the Socket, which is connected to the original HTTP server. And as such, communication can happen and I act as a proxy server.
Here's a screenshot with all the connections done right:
This proxy server is far from perfect, but the basic concept should be clear. This gave me some inspiration.
You use a streamreader on binary image data, that is not going to work. Not every binary is a valid ASCII encoded string. You should read the response as binary, and write it to the other stream as binary as well. You can try to convert it to ascii to print it to the console, but do not use the converted text to respond, because all the non-valid ascii characters will be converted to ?-s. I did modify your code to first read the response in a MemoryStream, and write that back. The data written to the console is still converted, but not user anywhere else.
static void Main(string[] args)
{
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;
WebRequest request;
WebResponse response;
// 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;
String[] input;
// Loop to receive all the data sent by the client.
while (stream.DataAvailable)
{
data = null;
i = stream.Read(bytes, 0, bytes.Length);
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine(String.Format("Received: {0}", data));
input = data.Split();
Console.WriteLine("\n\r\n input[1]" + input[1] + "\n");
Stream dataStream;
StreamReader reader;
string responseFromServer;
try
{
request = WebRequest.Create(input[1]);
response = request.GetResponse();
// Process the data sent by the client.
data = data.ToUpper();
dataStream = response.GetResponseStream();
MemoryStream ms = new MemoryStream();
dataStream.CopyTo(ms);
ms.Position = 0;
// Open the stream using a StreamReader for easy access.
reader = new StreamReader(ms);
// Read the content.
responseFromServer = reader.ReadToEnd();
// Display the content
Console.WriteLine(responseFromServer);
// Clean up the streams and the response.
byte[] msg = ms.ToArray();
// Send back a response.
stream.Write(msg, 0, msg.Length);
// Console.WriteLine("Sent: {0}", data);
//stream.Write();
reader.Close();
response.Close();
}
catch (System.UriFormatException e)
{
Console.WriteLine("Exception due to" + e.Data);
Console.WriteLine("Input[1] = " + input[1]);
}
data = null;
}
// 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();
}

Trying to read from NetworkStream crashes program, no exception or error

I'm trying to read data from a socket, however whenever I try to read the entire stream my program hangs. With no error or exception.
I can manually read say 4 bytes and it will work, however I no longer know the exact size of the data the server will send, therefore I wish to read the entire stream. What am I doing wrong?
It hangs when calling ReadToEnd().
Stream input = socket.GetStream();
byte[] request = new byte[5];
input.Write(request, 0, 5); //send request
StreamReader reader = new StreamReader(input);
if (input.CanRead == true)
{
string test = reader.ReadToEnd();
}
Your code canot know how long the stream is, it's possibly not ended so its going to continue to block until it has. Below is an example server and client (in no way is this a robust implementation) but if you consider the following code you should see how to send a request and receive a response:
public class Server
{
private readonly Thread _listenThread;
private readonly TcpListener _tcpListener;
public Server()
{
_tcpListener = new TcpListener(IPAddress.Any, 3000);
_listenThread = new Thread(Listen);
_listenThread.Start();
}
private void Listen()
{
var tcpListener = _tcpListener;
if (tcpListener != null)
{
tcpListener.Start();
}
while (true)
{
TcpClient client = _tcpListener.AcceptTcpClient();
Console.Out.WriteLine("Connection Accepted");
Thread clientThread = new Thread(DoWork);
clientThread.Start(client);
}
}
private void DoWork(object client)
{
TcpClient tcpClient = client as TcpClient;
if (tcpClient == null)
{
throw new ArgumentNullException("client", "Must pass client in");
}
using (NetworkStream clientStream = tcpClient.GetStream())
{
byte[] message = new byte[1024];
while (true)
{
Console.Out.WriteLine("Waiting for message");
int bytesRead = clientStream.Read(message, 0, 1024);
if (bytesRead == 0)
{
break;
}
ASCIIEncoding encoder = new ASCIIEncoding();
string received = encoder.GetString(message, 0, bytesRead);
Console.Out.WriteLine(String.Format("Read {0}", received));
if (received.Equals("Hello Server !"))
{
byte[] buffer = encoder.GetBytes("Hello Client!");
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
}
}
}
}
You would need a client that did something like this
static void Main(string[] args)
{
try
{
using (TcpClient clientSock = new TcpClient(IPAddress.Loopback.ToString(), 3000))
{
using (Stream clientStream = clientSock.GetStream())
{
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] helloMessage = encoder.GetBytes("Hello Server !");
clientStream.Write(helloMessage, 0, helloMessage.Length);
clientStream.Flush();
using (StreamReader streamReader = new StreamReader(clientStream))
{
while(true)
{
char[] buffer = new char[1024];
streamReader.Read(buffer,0, 1024);
Console.Out.WriteLine(new string(buffer));
}
}
}
}
Console.ReadLine();
}
catch (Exception)
{
// do something here
throw;
}
}

Categories