I have this web server I tried to make using TcpListener, but it won't accept about half of the requests I made. It simply hangs on AcceptTcpClient when the request is made, also it behaves the same on any port.
this.main = new Thread(() =>
{
while (this.running)
{
TcpClient c = this.t.AcceptTcpClient();
new Task(() =>
{
handleClient(c);
}).Start();
}
});
this.main.Start();
Maybe you can try something like this:
public void Start()
{
Console.WriteLine("Server started...");
TcpListener listener = new TcpListener(System.Net.IPAddress.Loopback, 1234);
listener.Start();
while (true)
{
TcpClient client = listener.AcceptTcpClient();
new Thread(new ThreadStart(() =>
{
HandleClient(client);
})).Start();
}
}
private void HandleClient(TcpClient client)
{
NetworkStream stream = client.GetStream();
StreamWriter writer = new StreamWriter(stream, Encoding.ASCII) { AutoFlush = true };
StreamReader reader = new StreamReader(stream, Encoding.ASCII);
string inputLine = reader.ReadLine();
Console.WriteLine("The client with name " + " " + inputLine + " is conected");
}
Related
In an Universal Windows Platform (UWP) app, I'm trying to send an object to a Windows form program using socket:
public void CreateListener()
{
TcpListener listener = new TcpListener(IPAddress.Any, port);
listener.Start();
while (true)
{
if (listener.Pending())
{
var childSocketThread = new Thread(() =>
{
string data = null;
var Client = listener.AcceptTcpClient();
using (NetworkStream ns = Client.GetStream())
using (StreamReader sr = new StreamReader(ns))
{
data = sr.ReadToEnd();
var Items = JsonConvert.DeserializeObject<Models.Orders>(data);
Process(Items);
ns.Flush();
ns.Close();
}
});
childSocketThread.IsBackground = true;
childSocketThread.Start();
}
else
{
Thread.Sleep(50); //<--- timeout
}
}
}
But receiving object stuck in ReadToEnd and never exit.
What should I do?
Seems you have problem when you want to send data, after flushing your StreamWriter object you have to use StreamReader as a response.
Stream streamIn = socket.InputStream.AsStreamForRead();
StreamReader reader = new StreamReader(streamIn);
string response = await reader.ReadLineAsync();
Hope this would help you.
I'm trying to communicate with a server.
This is my simple code:
System.Net.Sockets.TcpClient sock = new System.Net.Sockets.TcpClient();
string outputString = string.Empty;
sock.Connect("stack.overflow", 80);
NetworkStream ns = null;
StreamReader sr = null;
StreamWriter sw = null;
ns = sock.GetStream();
sr = new StreamReader(ns);
sw = new StreamWriter(ns) { NewLine = "\r\n", AutoFlush = true };
ns.ReadTimeout = 10;
sw.WriteLine("send data to server");
sw.Flush();
outputString = sr.ReadLine();
while (!string.IsNullOrEmpty(outputString))
{
System.Diagnostics.Debug.WriteLine(outputString);
outputString = sr.ReadLine();
}
(I know my code has room for improvement. It kept it simple for my test)
Everything works fine beside the ReadLine().
It doesn't do what I'm expecting it to do.
It reads all lines from the server and after the last line it just endlessly waits for a new line. At least for me it seems like it is waiting.
I thought it would stop after the last line and return null or something else.
Can someone explain me what the best practice is to get all lines from the server and move on?
I solved it like this:
public class ServerHandler
{
private BackgroundWorker serverWorker = new BackgroundWorker();
public event EventHandler ServerResponse;
private TcpClient socket;
private NetworkStream networkStream;
private StreamReader streamReader;
private StreamWriter streamWriter;
public ServerHandler()
{
System.Net.Sockets.TcpClient sock = new System.Net.Sockets.TcpClient();
serverWorker.WorkerSupportsCancellation = true;
serverWorker.DoWork += new DoWorkEventHandler(serverWorker_DoWork);
}
public void ConnectToServer()
{
socket = new TcpClient();
socket.Connect("stack.overflow", 80);
networkStream = socket.GetStream();
streamReader = new StreamReader(networkStream);
streamWriter = new StreamWriter(networkStream) { NewLine = "\r\n", AutoFlush = true };
SendMessage("some data");
}
public bool IsConnected
{
get { return socket.Connected; }
}
public void StartListening()
{
if (ServerResponse == null)
throw new Exception("There is no event to intercept the response!");
serverWorker.RunWorkerAsync();
}
private void SendMessage(string message)
{
streamWriter.WriteLine(message);
streamWriter.Flush();
}
private void serverWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
while (true)
{
string serverResponse = streamReader.ReadLine();
ServerResponse(serverResponse, new EventArgs());
}
}
}
Like willaien already said, the stream doesn't know when it ends. As long as you are communicating with the server you can wait for a response.
I put the code that listens to the server in a background worker, that always listens and that sends an event, when a new response appears.
I created a simple network game that uses TCP sockets in order to get the other player's data. I have two different classes, a server and a client. Everything was perfectly fine when I was only sending one message at a time like so:
Client:
public void ClientTester()
{
thread = new Thread(SendPosition);
thread.Start();
}
private void SendPosition()
{
while (true)
{
using (TcpClient client = new TcpClient())
{
client.Connect("127.0.0.1", 82);
using (NetworkStream n = client.GetStream())
{
BinaryWriter w = new BinaryWriter(n);
w.Write("Position:" + GameFiles.Player.Player.position.ToString());
w.Flush();
string msg = new BinaryReader(n).ReadString();
parseString(msg, "Position:", 9);
}
}
Thread.Sleep(60);
}
}
Server:
public void ServerTester()
{
thread = new Thread(TheadedMethod);
thread.Start();
}
private void TheadedMethod()
{
while (true)
{
TcpListener listener = new TcpListener(IPAddress.Any, 82);
listener.Start();
using (TcpClient c = listener.AcceptTcpClient())
using (NetworkStream n = c.GetStream())
{
parseString(msg, "Position:", 9);
BinaryWriter w = new BinaryWriter(n);
w.Write("Position:" + GameFiles.Player.Player.position.ToString());
w.Flush();
}
listener.Stop();
}
}
Here is the new code:
Client:
public void ClientTester()
{
thread = new Thread(SendPosition);
thread.Start();
SendMousePosition();
}
private void SendPosition()
{
while (true)
{
using (TcpClient client = new TcpClient())
{
client.Connect("127.0.0.1", 82);
using (NetworkStream n = client.GetStream())
{
BinaryWriter w = new BinaryWriter(n);
w.Write("Position:" + GameFiles.Player.Player.position.ToString());
w.Flush();
string msg = new BinaryReader(n).ReadString();
parseString(msg, "Position:", 9);
}
}
Thread.Sleep(60);
}
}
private void SendMousePosition()
{
using (TcpClient client = new TcpClient())
{
client.Connect("127.0.0.1", 82);
using (NetworkStream n = client.GetStream())
{
BinaryWriter w = new BinaryWriter(n);
w.Write("MousePosition:" + cursor.mousePosition());
w.Flush();
string msg = new BinaryReader(n).ReadString();
parseString(msg, "MousePosition:", 14);
}
}
}
Server:
public void ServerTester()
{
thread = new Thread(TheadedMethod);
thread.Start();
}
private void TheadedMethod()
{
while (true)
{
TcpListener listener = new TcpListener(IPAddress.Any, 82);
listener.Start();
using (TcpClient c = listener.AcceptTcpClient())
using (NetworkStream n = c.GetStream())
{
string msg = new BinaryReader(n).ReadString();
if (msg == "Position:")
{
parseString(msg, "Position:", 9);
BinaryWriter w = new BinaryWriter(n);
w.Write("Position:" + GameFiles.Player.Player.position.ToString());
w.Flush();
}
if (msg == "MousePosition:")
{
parseString(msg, "MousePosition:", 14);
BinaryWriter w = new BinaryWriter(n);
w.Write("MousePosition:" + cursor.mousePosition());
w.Flush();
}
}
listener.Stop();
}
}
When I try to send two messages in I receive an error:
Unable to read beyond the end of the stream.
on this line from the client's method SendPosition():
string msg = new BinaryReader(n).ReadString();
Why doesn't this work even though I have created a new instance of BinaryReader? Shouldn't the server automatically respond to each message sent to it?
You are doing two things wrong: The fist is that you create and re-create the connection all the time. Instead create the listener once, enter the loop and read messages. Setting up a new connection in TCP ads a lot of overhead, especially if you're just sending small messages. Same thing in the client, connect once, and then send when needed.
The second problem is that TCP is a streaming protocol, and that there is no message boundaries. That means that when you read from a TCP connection you can't know beforehand how much data you will read, you need to provide a way to separate messages yourself: You can add message boundaries, you can prepend each message with a header containing the message size, of you have have all messages being the same fixed size. Either way, you might have to read multiple times to get a complete message, or one read could give you more than one message.
Regarding the second problem, you can't of course attempt to read more than have been received, which is probably what the error message is telling you.
I have two basic console apps that communicate "over the network" even though all of the communication takes place on my local machine.
Client code:
public static void Main()
{
while (true)
{
try
{
TcpClient client = new TcpClient();
client.Connect("127.0.0.1", 500);
Console.WriteLine("Connected.");
byte[] data = ASCIIEncoding.ASCII.GetBytes(new FeederRequest("test", TableType.Event).GetXmlRequest().ToString());
Console.WriteLine("Sending data.....");
using (var stream = client.GetStream())
{
stream.Write(data, 0, data.Length);
stream.Flush();
Console.WriteLine("Data sent.");
}
client.Close();
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.StackTrace);
Console.ReadLine();
}
}
}
Server code:
public static void Main()
{
try
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
Console.WriteLine("Starting TCP listener...");
TcpListener listener = new TcpListener(ipAddress, 500);
listener.Start();
Console.WriteLine("Server is listening on " + listener.LocalEndpoint);
while (true)
{
Socket client = listener.AcceptSocket();
Console.WriteLine("\nConnection accepted.");
var childSocketThread = new Thread(() =>
{
Console.WriteLine("Reading data...\n");
byte[] data = new byte[100];
int size = client.Receive(data);
Console.WriteLine("Recieved data: ");
for (int i = 0; i < size; i++)
Console.Write(Convert.ToChar(data[i]));
//respond to client
Console.WriteLine("\n");
client.Close();
Console.WriteLine("Waiting for a connection...");
});
childSocketThread.Start();
}
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.StackTrace);
Console.ReadLine();
}
}
How can I alter both of these applications so that when the Server has received the data, it responds to the Client with some kind of confirmation?
Thanks in advance!
Here a short example how I would do it:
Server:
class Server
{
static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Any, 1500);
listener.Start();
TcpClient client = listener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
// Create BinaryWriter for writing to stream
BinaryWriter binaryWriter = new BinaryWriter(stream);
// Creating BinaryReader for reading the stream
BinaryReader binaryReader = new BinaryReader(stream);
while (true)
{
// Read incoming information
byte[] data = new byte[16];
int receivedDataLength = binaryReader.Read(data, 0, data.Length);
string stringData = Encoding.ASCII.GetString(data, 0, receivedDataLength);
// Write incoming information to console
Console.WriteLine("Client: " + stringData);
// Respond to client
byte[] respondData = Encoding.ASCII.GetBytes("respond");
Array.Resize(ref respondData, 16); // Resizing to 16 byte, because in this example all messages have 16 byte to make it easier to understand.
binaryWriter.Write(respondData, 0, 16);
}
}
}
Client:
class Client
{
private static void Main(string[] args)
{
Console.WriteLine("Press any key to start Client");
while (! Console.KeyAvailable)
{
}
TcpClient client = new TcpClient();
client.Connect("127.0.0.1", 1500);
NetworkStream networkStream = client.GetStream();
// Create BinaryWriter for writing to stream
BinaryWriter binaryWriter = new BinaryWriter(networkStream);
// Creating BinaryReader for reading the stream
BinaryReader binaryReader = new BinaryReader(networkStream);
// Writing "test" to stream
byte[] writeData = Encoding.ASCII.GetBytes("test");
Array.Resize(ref writeData, 16); // Resizing to 16 byte, because in this example all messages have 16 byte to make it easier to understand.
binaryWriter.Write(writeData, 0, 16);
// Reading response and writing it to console
byte[] responeBytes = new byte[16];
binaryReader.Read(responeBytes, 0, 16);
string response = Encoding.ASCII.GetString(responeBytes);
Console.WriteLine("Server: " + response);
while (true)
{
}
}
}
I hope this helps! ;)
You can perform both Read and Write on the same stream.
After you send all the data over, just call stream.Read as in
using (var stream = client.GetStream())
{
stream.Write(data, 0, data.Length);
stream.Flush();
Console.WriteLine("Data sent.");
stream.Read(....); //added sync read here
}
MSDN documentation on TcpClient has an example as well http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.aspx
If you want feed back such as reporting # of bytes received so far, you'll have to use async methods.
Here's an example of what (I think) you want to do:
static void Main(string[] args) {
var server = new Task(Server);
server.Start();
System.Threading.Thread.Sleep(10); // give server thread a chance to setup
try {
TcpClient client = new TcpClient();
client.Connect("127.0.0.1", 1500);
Console.WriteLine("Connected.");
var data = new byte[100];
var hello = ASCIIEncoding.ASCII.GetBytes("Hello");
Console.WriteLine("Sending data.....");
using (var stream = client.GetStream()) {
stream.Write(hello, 0, hello.Length);
stream.Flush();
Console.WriteLine("Data sent.");
// You could then read data from server here:
var returned = stream.Read(data, 0, data.Length);
var rec = new String(ASCIIEncoding.ASCII.GetChars(data, 0, data.Length));
rec = rec.TrimEnd('\0');
if (rec == "How are you?") {
var fine = ASCIIEncoding.ASCII.GetBytes("fine and you?");
stream.Write(fine, 0, fine.Length);
}
}
client.Close();
Console.ReadLine();
}
catch (Exception e) {
Console.WriteLine("Error: " + e.StackTrace);
Console.ReadLine();
}
}
public static void Server() {
try {
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
Console.WriteLine("*Starting TCP listener...");
TcpListener listener = new TcpListener(ipAddress, 1500); // generally use ports > 1024
listener.Start();
Console.WriteLine("*Server is listening on " + listener.LocalEndpoint);
Console.WriteLine("*Waiting for a connection...");
while (true) {
Socket client = listener.AcceptSocket();
while (client.Connected) {
Console.WriteLine("*Connection accepted.");
Console.WriteLine("*Reading data...");
byte[] data = new byte[100];
int size = client.Receive(data);
Console.WriteLine("*Recieved data: ");
var rec = new String(ASCIIEncoding.ASCII.GetChars(data, 0, size));
rec = rec.TrimEnd('\0');
Console.WriteLine(rec);
if (client.Connected == false) {
client.Close();
break;
}
// you would write something back to the client here
if (rec == "Hello") {
client.Send(ASCIIEncoding.ASCII.GetBytes("How are you?"));
}
if (rec == "fine and you?") {
client.Disconnect(false);
}
}
}
listener.Stop();
}
catch (Exception e) {
Console.WriteLine("Error: " + e.StackTrace);
Console.ReadLine();
}
}
}
Keep in mind that data sent via sockets can arrive fragmented (in different packets). This doesn't usually happen with the packets are small.
I'm writing a client/server (as many of you probably already know!). The server is going to be sending data to the client. However, the client can connect once and after that it never attempts to connect again once the connection has been terminated. Similarly, once the server has sent it's message it will ignore future attempts to connect.
Server:
public Server(String p)
{
path = p;
listener = new TcpListener(IPAddress.Any, 1337);
listener.Start();
Thread t = new Thread(new ThreadStart(ListenForClients));
t.IsBackground = true;
t.Start();
}
private void ListenForClients()
{
TcpClient client = listener.AcceptTcpClient();
new Thread(new ParameterizedThreadStart(HandleClientCom)).Start(client);
}
private void HandleClientCom(object TcpClient)
{
new Dialog("Connection", "Connection established.");
TcpClient client = (TcpClient)TcpClient;
NetworkStream stream = client.GetStream();
//SslStream stream = new SslStream(client.GetStream());
//stream.AuthenticateAsServer(new X509Certificate(path + "\\ServerCert.cer"));
ASCIIEncoding encoder = new ASCIIEncoding();
String str = "This is a long piece of text to send to the client.";
byte[] bytes = encoder.GetBytes(str);
stream.Write(bytes, 0, bytes.Length);
stream.Flush();
}
Client:
public TCP(BackgroundWorker b)
{
try
{
bw = b;
client = new TcpClient();
IPEndPoint server = new IPEndPoint(IPAddress.Parse(srv), 1337);
client.Connect(server); //Connect to the server
bw.ReportProgress(0); //Update the GUI with the connection status
Thread t = new Thread(new ParameterizedThreadStart(HandleComms));
t.IsBackground = true;
t.Start(client);
}
catch (Exception ex)
{
lastException = ex;
}
}
public void HandleComms(object c)
{
Boolean keepListening = true;
TcpClient client = (TcpClient)c;
NetworkStream stream = client.GetStream();
//stream = new SslStream(client.GetStream());
//stream.AuthenticateAsClient(srv);
byte[] msg = new byte[4096]; ;
int bytesRead = 0;
while (keepListening)
{
try
{
bytesRead = stream.Read(msg, 0, 4096);
}
catch (Exception ex)
{
lastException = ex;
}
if (bytesRead > 0)
{
StreamWriter writer = new StreamWriter("C:\\Users\\Chris\\Desktop\\ClientLog.txt");
ASCIIEncoding encoder = new ASCIIEncoding();
rx = encoder.GetString(msg);
writer.WriteLine(rx);
keepListening = false;
writer.Close();
}
}
}
Sorry for huge amounts of code. Can anyway point out where I've gone wrong?
Once you've accepted the connection, you'll need to begin listening again.
Try just making this change:
private void ListenForClients()
{
while(true)
{
TcpClient client = listener.AcceptTcpClient();
new Thread(new ParameterizedThreadStart(HandleClientCom)).Start(client);
}
}