I just made a C# socket server and it works perfectly, but if I would like to make it to be able to listen the inputs the program crashes. My question is: how can I make to continuously listen after the clients commands.
Here is my code:
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace mc_server
{
class Program
{
private static TcpListener serverSocket;
private static TcpClient clientSocket;
private static StreamReader reader;
private static StreamWriter writer;
private static int PORT = 5000;
static void Main(string[] args)
{
Console.WriteLine(DateTime.Now.ToString() + " >> Server starting...");
StartServer();
Console.ReadKey(true);
serverSocket.Stop();
}
private static void StartServer()
{
try
{
serverSocket = new TcpListener(IPAddress.Any, PORT);
serverSocket.Start();
Console.WriteLine(DateTime.Now.ToString() + " >> Server started");
while (true)
{
clientSocket = serverSocket.AcceptTcpClient();
reader = new StreamReader(clientSocket.GetStream());
writer = new StreamWriter(clientSocket.GetStream());
StartListening();
}
}
catch (Exception e)
{
if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
Console.WriteLine(DateTime.Now.ToString() + " [ERR]: Internet connection unavailable! (" + e.ToString() + ")");
else
Console.WriteLine(DateTime.Now.ToString() + " [ERR]: Server can't be started! (" + e.ToString() + ")");
}
}
private static void StartListening()
{
try
{
string line;
//while (true)
//{
line = reader.ReadLine();
if (line.Contains("connected"))
{
Console.WriteLine(DateTime.Now.ToString() + " >> Remote connected");
}
else if (line.Contains("get_dir"))
{
Console.WriteLine("in_get_dir");
foreach (string directory in Directory.GetDirectories(path))
{
DirectoryInfo dir_name = new DirectoryInfo(directory);
string dirName = dir_name.Name;
writer.WriteLine(line);
}
}
//}
}
catch (Exception e)
{
Console.WriteLine(DateTime.Now.ToString() + " [ERR]: " + e.ToString() + ")");
}
}
}
}
Thank you so much for your help!
Regards, Stanley.
I just made a C# socket server and it works perfectly, but if I would like to make it to be able to listen the inputs the program crashes.
I am not sure what you meant by that, but I think you have a problem in receiving/reading the response.
serverSocket = new TcpListener(IPAddress.Any, PORT);
serverSocket.Start();
You've created a TcpListener named 'serverSocket'. Now let's create a socket that helps us send and receive data between the server and the client. Creating a Streamwriter and Streamreader is too long and complicated. You'll have to deal with flushing, disposing, and closing them.
Here's my 3 simplified guide of using Socket to communicate:
1.) Creating a Socket:
Socket socket = serverSocket.AcceptSocket(); // This is a
//synchronous function. It will not execute the next line until a client
//connects to the server
2.) Sending data:
socket.Send(Encoding.ASCII.GetBytes("I am sending a short text to
the client")); // This will send the text to client. It ONLY accepts byte
//array, therefore we have to convert it from string to byte array to be
//able
//to send it.
3.) Receiving/Reading Data:
// For Receiving Text from the Client
byte[] responseByteArray = new byte[socket.ReceiveBufferSize]; //
//This will create a byte array to store the data. socket.ReceiveBufferSize
//will tells us the length of the data sent in byte array (not string yet)
int responseLength = socket.Receive(responseByteArray); // Tells us
//the length of the response in byte array (not string yet)
string response = null; // We will create a variable 'response' to
//store the final result of the conversion
for (int i = 0; i < responseLength; i++) // Loop to convert All byte
//from byte array to string
{
response = response + (char)responseByteArray[i]; // Converts
//every single byte of character to char
}
Console.WriteLine(response); // Prints out the final result in
//string
You can use async/await keywords to read & write data asynchronously on the sockets.
That way, your input logic will stay separate. If you use async/await, you won't have to manage threads manually.
Related
so I've made a C# TCP server, however whenever I connected multiple clients for a test, the whole device starts to lag out and the memory goes to 500 MB, earlier 1GB. I understand that this has to do with code structure and so however I'm not sure what's really causing this.
Image.
Console.
Basically, here's my server class.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Roleplay_Flash_Server.assets.communication
{
class server
{
private static TcpListener serverHandle;
private const string prefix = "[communication->server.cs] ";
private static bool responded = false;
public static void init(int port)
{
serverHandle = new TcpListener(IPAddress.Any, port);
serverHandle.Start();
Console.WriteLine("Waiting on a client...");
while (responded == false)
{
serverHandle.BeginAcceptTcpClient(HandleAsyncConnection, serverHandle);
//responded = false;
}
}
private static void HandleAsyncConnection(IAsyncResult response)
{
responded = true;
serverHandle.BeginAcceptTcpClient(HandleAsyncConnection, serverHandle);
TcpClient client = serverHandle.EndAcceptTcpClient(response);
communication.client.incoming.connection(client);
communication.client.events.pingIntervalEvent.init(client);
communication.client.events.handshakeEvent.init(client);
while(true)
{
string test = readRequest(client);
}
destruct(client);
}
public static string readRequest(TcpClient socket)
{
byte[] data = new byte[1024];
int response = socket.Client.Receive(data);
if (response == 0) return "";
string clientIP = ((IPEndPoint)socket.Client.RemoteEndPoint).Address.ToString();
string clientPort = ((IPEndPoint)socket.Client.RemoteEndPoint).Port.ToString();
Console.Write(prefix + "Received data from {#" + "?" + "}, {" + clientIP + ":" + clientPort + "}: " + Encoding.ASCII.GetString(data, 0, response));
return Encoding.ASCII.GetString(data, 0, response);
}
private static void destruct(TcpClient socket)
{
string clientIP = ((IPEndPoint)socket.Client.RemoteEndPoint).Address.ToString();
string clientPort = ((IPEndPoint)socket.Client.RemoteEndPoint).Port.ToString();
Console.Write(prefix + "Lost connection with {#" + "?" + "}, {" + clientIP + ":" + clientPort + "}.");
socket.Close();
}
}
}
Edit: All classes which may be causing this memory overflow:
https://pastebin.com/eB54fJY2
https://pastebin.com/LW2A7RZk
https://pastebin.com/t9YvTNsj
https://pastebin.com/C18du82K
So I've fixed this issue by simply removing the BeginAcceptTcpClient from the Async callback, this was causing the function to be called in the infinite loop but also in another callback called from the loop, making excessive memory overflow.
I want to add network one-on-one support for my Battleship game, and found this tutorial regarding server-client network programming:
http://csharp.net-informations.com/communications/csharp-multi-threaded-server-socket.htm
The code I'm using is the following, more or less just taken from there with some adjustments:
public class HandleClient
{
TcpClient clientSocket;
string clientNumber;
public void StartClient(TcpClient inClientSocket, string clientNumber)
{
this.clientSocket = inClientSocket;
this.clientNumber = clientNumber;
Thread clientThread = new Thread(DoChat);
clientThread.Start();
}
private void DoChat()
{
int requestCount = 0;
byte[] inBytes = new byte[10025];
string dataFromClient = null;
byte[] outBytes = null;
string rCount;
string serverResponse = null;
while (true)
{
try
{
requestCount++;
NetworkStream stream = clientSocket.GetStream();
stream.Read(inBytes, 0, (int)clientSocket.ReceiveBufferSize);
dataFromClient = Encoding.ASCII.GetString(inBytes);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$$"));
Console.WriteLine(" >> From client " + clientNumber + dataFromClient);
rCount = Convert.ToString(requestCount);
serverResponse = "Server to client " + clientNumber + ": " + rCount;
outBytes = Encoding.ASCII.GetBytes(serverResponse);
stream.Write(outBytes, 0, outBytes.Length);
stream.Flush();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}
and
class BattleshipServer
{
static void Main(string[] args)
{
TcpListener serverSocket = new TcpListener(IPAddress.Any, 8888);
TcpClient clientSocket = default(TcpClient);
int counter = 0;
serverSocket.Start();
while (true)
{
if (counter < 2)
{
counter++;
clientSocket = serverSocket.AcceptTcpClient();
Console.WriteLine("Client " + counter + " connected.");
HandleClient client = new HandleClient();
client.StartClient(clientSocket, counter.ToString());
}
}
clientSocket.Close();
serverSocket.Stop();
Console.WriteLine(" >> " + "exit");
Console.ReadLine();
}
}
However, I wonder about the last few lines just above this. Visual Studio complains about this code being unreachable, and I can see why. Is there any reason behind this code being there?
Also, I wonder what keeps counter from going up all the time? Is serverSocket.AcceptTcpClient() keeping the program "waiting" until another client connects maybe?
Thanks! And if you know of any other good sources to learn about this, I'll be glad to hear them :) Since I'd still have to adjust the above code by a good lot to make my game "wait" for data from the other player, restrict the player count, and so on.
The typo in the example (handleClinet()) may hint that the code was never reviewed; and you're right, the code won't leave the while block in this case.
The counter appears to serve as an identification of each client, as the introduction says "can handle multiple clients at the same time".
In your case, a one-on-one game, you probably want a single serverSocket.AcceptTcpClient and start the game after some basic information has been exchanged (ie. player names of both ends communicated), and you won't need that while loop there.
In the tcp header packet their is a field which mentions the total size of packet. I have implemented my server which is listening to multiple client in following way
int numberOfClientsYouNeedToConnect = int.Parse(Console.ReadLine());
for (int i = 0; i < numberOfClientsYouNeedToConnect; i++)
{
Thread newThread = new Thread(new ThreadStart(Listeners));
newThread.Start();
}
public static void Listeners()
{
try
{
Socket socketForClient = tcpListener.AcceptSocket();
if (socketForClient.Connected)
{
Console.WriteLine("Client : " + socketForClient.RemoteEndPoint + " is now connected to server.");
NetworkStream networkStream = new NetworkStream(socketForClient);
//networkStream.ReadTimeout = 30;
System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(networkStream);
System.IO.StreamReader streamReader = new System.IO.StreamReader(networkStream);
while (true)
{
string theString = streamReader.ReadLine();
//Console.WriteLine(theString);
byte[] input_stream = extra_function.ConvertHexToString(theString);
for (int i = 0; i < input_stream.Length; i++)
{
// Console.WriteLine("hi");
Console.Write(input_stream[i]);
}
if (theString != "exit")
{
// original message from client
Console.WriteLine("------------------------------------------------------------------------------");
Console.WriteLine("Message recieved from client(" + socketForClient.RemoteEndPoint + ") : " + theString);
// ASCII code for the message from client
Console.Write("ASCII Code for message is : ");
foreach (char c in theString)
{
Console.Write(System.Convert.ToInt32(c) + " ");
}
}
}
But my problem is that server without receiving complete packet it starts processing it while other part of packet comes little later. So how can I change my code so that server receives complete packet and then process it. The size of the total packet is included in the header of packet. The server should wait till it receive that much bytes from client or wait till some time for getting complete packet.
Did you try StreamReader.ReadToEnd() instead of StreamReader.ReadLine() ?
This is a program to search for strings from a file. The string required by the client is given from the client side, in my case, using telnet. The program I have written is a server side one. It accepts multiple clients.
But, the problems I am unable rectify are-
It doesn't check for strings from the file.
As soon as the client gets connected, the client cannot type in the strings they want to search in that particular file.
It doesn't send the reply back (i.e. If the string is present in the file or not) to the client. Its only shown on the server side.
How do I proceed further? Could someone tell me where am I going wrong? Could someone please help me out with the code?
This is my try at the program..
class Program
{
static void Main(string[] args)
{
IPAddress ipad = IPAddress.Parse("192.168.0.181");
TcpListener serversocket = new TcpListener(ipad, 8888);
TcpClient clientsocket = default(TcpClient);
Byte[] bytes = new Byte[256];
serversocket.Start();
Console.WriteLine(">> Server Started");
while(true)
{
clientsocket = serversocket.AcceptTcpClient();
Console.WriteLine("Accepted Connection From Client");
LineMatcher lm = new LineMatcher(clientsocket);
Thread thread = new Thread(new ThreadStart(lm.Run));
thread.Start();
Console.WriteLine("Client connected");
}
Console.WriteLine(" >> exit");
Console.ReadLine();
clientsocket.Close();
serversocket.Stop();
}
}
public class LineMatcher //I've jumbled it up here. Don't know what exactly to do..
{
public string fileName = "c:/myfile2.txt";
private TcpClient _client;
public LineMatcher(TcpClient client)
{
_client = client;
}
public void Run()
{
try
{
StreamReader sr = new StreamReader("c:/myfile2.txt");
using (var reader = new StreamReader(_client.GetStream()))
{
string line ="";
int lineNumber = 0;
while (null != (line = sr.ReadLine()))
{
lineNumber += 1;
byte[] data = new byte[1024];
NetworkStream stream = _client.GetStream();
//if (line.Equals(line))
for (int ct = stream.Read(data,0, data.Length-1); 0 < ct; ct = stream.Read(data,0,data.Length-1))
line += Encoding.ASCII.GetString(data, 0, ct);
line = line.Trim();
{
lineNumber.ToString();
data = Encoding.ASCII.GetBytes(line);
_client.Client.Send(data, data.Length, SocketFlags.None);
Console.WriteLine("Line {0} matches {1}", lineNumber, line);
}
}
}
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.ToString());
}
Console.WriteLine("Closing client");
_client.Close();
}
}
I think you got some pieces in your Run-method swapped - here is a version that should do the job:
public void Run()
{
byte[] data;
try
{
using (var r = new StreamReader("c:/myfile2.txt"))
{
string line ="";
int lineNumber = 0;
while (null != (line = r.ReadLine()))
{
data = Encoding.ASCII.GetBytes(line + "\n");
_client.Client.Send(data, data.Length, SocketFlags.None);
}
}
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.ToString());
}
Console.WriteLine("Closing client");
_client.Close();
}
Please note that I'm not 100% sure what you are trying to do (I think you want your textfile send line-by-line to your Terminal) - so you might have to change some bits here and there.
Don't know where the Stream-messes in your code came from but I guess you tried various tutorials/snippets and forgot to clean up ;)
I got a working server in C# and a working client in Java (Android). It's totally working, but the connection itself is only one-wayed. Only the client can send data to the server. I tried to make the connection two-sided, but the code not working by an unknown reason.
Where I do it wrong?
C#- server
public void SendBack(string message, NetworkStream stream)
{
if (stream.CanWrite)
{
byte[] candy = Encoding.ASCII.GetBytes(message + ";");
stream.Write(candy, 0, candy.Length);
stream.Flush();
Console.WriteLine("[SENT] " + message);
}
else { Console.WriteLine("ERROR! CANNOT WRITE ON NETWORKSTREAM!"); }
}
Java- client
//Creating the stream in the constructor
bReader = new BufferedReader(new InputStreamReader(gSocket.getInputStream()));
new Thread (new Runnable(){
public void run() {
Log.d(TAG, "Started listerner...");
ListenServer();
}
}).start();
//The function itself
private void ListenServer(){
try
{
String inputLine = "";
while (true){
inputLine = bReader.readLine();
if (inputLine != null) Log.d(TAG, "Got: " + inputLine);
}
}
catch (IOException e){ Log.d(TAG, "Could not listen to sever!"); }
}
Edit: forget to mention whats the actual problem... I start the server, behaves like usual, client can send data, which the server can interpret the message. Hoverwer, if the server sends something, the client do nothing. I mean, it does not execute the
Log.d(TAG, "Got: " + inputLine);
code.
It could be that the server is not sending the line-feed and/or carriage-return. BufferedReader.readLine()(link) expects it. You can construct a StreamWriter with the incoming stream, and use one of the WriteLine methods.