C# TCP Server combining received data - c#

I'm working on a rough TCP Server/Client. It works like this:
Client sends message to server > Server sends all user data to each client. I have this in a loop as I'm going to use this transfer of data for multiplayer in a game. However, for some reason my server will combine incoming data into one string instead of reading it line by line. For example, it should read something like
john:0|0
for user data, but instead it reads like john:0|0john:0|0john:0|0john:0|0
I've tried setting a delay on sending and receiving, but it only seems to work if I delay more than 100ms.
Server
class Program
{
private static Socket _serverSocket;
private static readonly List<Socket> _clientSockets = new List<Socket>();
private const int _BUFFER_SIZE = 2048;
private const int _PORT = 100;
private static readonly byte[] _buffer = new byte[_BUFFER_SIZE];
public static bool clientConnected = false;
public static Socket current;
public static int delay = 100; //65
public static string username = "";
public static int dataSent = 0;
public static int dataReceived = 0;
public static List<Player> players = new List<Player>();
static void Main()
{
Console.Title = "Server";
SetupServer();
Console.ReadLine(); // When we press enter close everything
CloseAllSockets();
}
private static void SetupServer()
{
Console.WriteLine("Setting up server...");
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Bind(new IPEndPoint(IPAddress.Any, _PORT));
_serverSocket.Listen(5);
_serverSocket.BeginAccept(AcceptCallback, null);
Console.WriteLine("Server setup complete");
Console.WriteLine("Listening on port: " + _PORT);
}
private static void CloseAllSockets()
{
foreach (Socket socket in _clientSockets)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
_serverSocket.Close();
}
private static void AcceptCallback(IAsyncResult AR)
{
Socket socket;
try
{
socket = _serverSocket.EndAccept(AR);
}
catch (ObjectDisposedException) // I cannot seem to avoid this (on exit when properly closing sockets)
{
return;
}
_clientSockets.Add(socket);
socket.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, socket);
Console.WriteLine("Client connected: " + socket.RemoteEndPoint);
_serverSocket.BeginAccept(AcceptCallback, null);
clientConnected = true;
}
private static void ReceiveCallback(IAsyncResult AR)
{
current = (Socket)AR.AsyncState;
int received = 0;
try
{
received = current.EndReceive(AR);
}
catch (SocketException)
{
Console.WriteLine("Client forcefully disconnected");
current.Close(); // Dont shutdown because the socket may be disposed and its disconnected anyway
_clientSockets.Remove(current);
return;
}
byte[] recBuf = new byte[received];
Array.Copy(_buffer, recBuf, received);
string text = Encoding.ASCII.GetString(recBuf);
if (text.Contains("newuser:"))
{
string newuser = text.Replace("newuser:", "");
Player newPlayer = new Player(newuser, current.RemoteEndPoint.ToString());
players.Add(newPlayer);
SendString("newuser:" + newuser);
Console.WriteLine(newuser + " has joined the game.");
}
else
{
Console.WriteLine(text); //This is where the client text gets mashed together
}
current.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
}
public static void SendString(string message)
{
try
{
byte[] data = Encoding.ASCII.GetBytes(message.ToString());
current.Send(data);
//current.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
dataSent++;
}
catch (Exception ex)
{
Console.WriteLine("Client disconnected!" + ex.Message);
}
Console.WriteLine(dataSent);
}
}
Client.cs
public static class Client
{
public static string Username = "null";
public static int delay = 85;
public static bool hasLoggedin = false;
public static int dataSent = 0;
private static readonly Socket _clientSocket = new Socket
(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private const int port = 100;
public static void Init()
{
Console.Title = "Client";
ConnectToServer();
Exit();
}
private static void ConnectToServer()
{
int attempts = 0;
while (!_clientSocket.Connected)
{
try
{
attempts++;
Console.Write("Username: ");
//Username = Console.ReadLine();
Username = "Matt";
LocalPlayer.username = Username;
Console.Write("IP: ");
string ip = "192.168.0.2";
Console.WriteLine("Port[default]: " + port);
Console.WriteLine("Connection attempt to " + ip + ": " + attempts + " attempts");
IPAddress ipAd = IPAddress.Parse(ip);
_clientSocket.Connect(ipAd, port);
}
catch (SocketException e)
{
Console.Clear();
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
Console.WriteLine("Connected!");
SendLoginPacket();
}
public static void SendLoginPacket()
{
if (hasLoggedin == false)
{
SendString("newuser:" + Username);
Thread.Sleep(delay);
hasLoggedin = true;
}
RequestLoop();
}
private static void RequestLoop()
{
while (true)
{
//SendData();
ReceiveResponse();
}
}
private static void Exit()
{
_clientSocket.Shutdown(SocketShutdown.Both);
_clientSocket.Close();
Environment.Exit(0);
}
public static void SendData()
{
string data = LocalPlayer.username + ":" + LocalPlayer.velocity.X + "|" + LocalPlayer.velocity.Y;
SendString(data);
}
private static void SendString(string text)
{
byte[] buffer = Encoding.ASCII.GetBytes(text);
Console.WriteLine("Sent: " + text);
_clientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None);
dataSent++;
Thread.Sleep(delay);
Console.WriteLine(dataSent);
}
private static void ReceiveResponse()
{
var buffer = new byte[2048];
int received = _clientSocket.Receive(buffer, SocketFlags.None);
if (received == 0) return;
var data = new byte[received];
Array.Copy(buffer, data, received);
string text = Encoding.ASCII.GetString(data);
if (text.Contains("newuser:"))
{
string str = text.Replace("newuser:", "");
if (!(str == LocalPlayer.username))
{
Player player = new Player(str, Globals.Content);
Globals.players.Add(player);
Console.WriteLine(str + " has joined the game.");
}
}
Console.WriteLine("Clients connected: " + Globals.players.Count());
}
}
How can I change the server so it reads incoming data one at a time, instead of mashing it into one big string?
EDIT: Note the LocalPlayer class is sending it's movement position using the Client class.

This is because the TCP/IP protocol provides the stream of the data (bytes). If the strings are not separated explicitly, they are "concatenated" because of "streaming".
It is required to "join" the messages using the "separator" when sending and "split" the messages using the "separator" when receiving. One of the following alternatives could be considered to implement the "separator" concept:
Introduce the "end-of-the-message" marker.
Introduce the message header which contains the length of the message.
The small article, TCP/IP client-server application: exchange with string messages, may be useful to understand the mentioned alternatives.
Update
I would like to recommend implementing the "messaging" appropriately.
Although it seems there is no the reason to compare the source code because it of its principal flaw (lack of "messaging" mechanism), the source code I have used to test the Client and the Server is attached.
Client
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
internal sealed class Program
{
private const int Port = 100;
private readonly Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private bool hasLoggedin;
private int dataSent;
public static void Main()
{
var client = new Program();
client.ConnectToServer();
client.Exit();
}
private void ConnectToServer()
{
int attempts = 0;
while (!clientSocket.Connected)
{
try
{
attempts++;
string ip = "127.0.0.1";
Console.WriteLine("Port[default]: " + Port);
Console.WriteLine("Connection attempt to " + ip + ": " + attempts + " attempts");
var address = IPAddress.Parse(ip);
clientSocket.Connect(address, Port);
}
catch (SocketException e)
{
Console.Clear();
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
Console.WriteLine("Connected!");
SendLoginPacket();
}
private void SendLoginPacket()
{
if (hasLoggedin == false)
{
SendString("newuser:" + Guid.NewGuid());
hasLoggedin = true;
}
RequestLoop();
}
private void RequestLoop()
{
while (true)
{
SendData();
ReceiveResponse();
}
}
private void Exit()
{
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
private void SendData()
{
const string Data = "username:100|200";
SendString(Data);
}
private void SendString(string text)
{
byte[] buffer = Encoding.ASCII.GetBytes(text);
Console.WriteLine("Sent: " + text);
clientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None);
dataSent++;
Console.WriteLine(dataSent);
}
private void ReceiveResponse()
{
var buffer = new byte[2048];
int received = clientSocket.Receive(buffer, SocketFlags.None);
if (received == 0)
{
return;
}
var data = new byte[received];
Array.Copy(buffer, data, received);
string text = Encoding.ASCII.GetString(data);
if (text.Contains("newuser:"))
{
string str = text.Replace("newuser:", string.Empty);
Console.WriteLine(str + " has joined the game.");
}
Console.WriteLine("Clients connected.");
}
}
Server
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
internal sealed class Program
{
private const int BufferSize = 2048;
private const int Port = 100;
private readonly List<Socket> clientSockets = new List<Socket>();
private readonly byte[] buffer = new byte[BufferSize];
private readonly List<Player> players = new List<Player>();
private Socket serverSocket;
private Socket current;
private int dataSent;
public static void Main()
{
var program = new Program();
program.SetupServer();
Console.ReadLine();
program.CloseAllSockets();
}
private void SetupServer()
{
Console.WriteLine("Setting up server...");
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(new IPEndPoint(IPAddress.Any, Port));
serverSocket.Listen(5);
serverSocket.BeginAccept(AcceptCallback, null);
Console.WriteLine("Server setup complete");
Console.WriteLine("Listening on port: " + Port);
}
private void CloseAllSockets()
{
foreach (Socket socket in clientSockets)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
serverSocket.Close();
}
private void AcceptCallback(IAsyncResult AR)
{
Socket socket;
try
{
socket = serverSocket.EndAccept(AR);
}
catch (ObjectDisposedException) // I cannot seem to avoid this (on exit when properly closing sockets)
{
return;
}
clientSockets.Add(socket);
socket.BeginReceive(buffer, 0, BufferSize, SocketFlags.None, ReceiveCallback, socket);
Console.WriteLine("Client connected: " + socket.RemoteEndPoint);
serverSocket.BeginAccept(AcceptCallback, null);
}
private void ReceiveCallback(IAsyncResult AR)
{
current = (Socket)AR.AsyncState;
int received = 0;
try
{
received = current.EndReceive(AR);
}
catch (SocketException)
{
Console.WriteLine("Client forcefully disconnected");
current.Close(); // Dont shutdown because the socket may be disposed and its disconnected anyway
clientSockets.Remove(current);
return;
}
byte[] recBuf = new byte[received];
Array.Copy(buffer, recBuf, received);
string text = Encoding.ASCII.GetString(recBuf);
if (text.Contains("newuser:"))
{
string newuser = text.Replace("newuser:", string.Empty);
Player newPlayer = new Player(newuser, current.RemoteEndPoint.ToString());
players.Add(newPlayer);
SendString("newuser:" + newuser);
Console.WriteLine(newuser + " has joined the game.");
}
else
{
// This is where the client text gets mashed together.
Console.WriteLine(text);
}
current.BeginReceive(buffer, 0, BufferSize, SocketFlags.None, ReceiveCallback, current);
}
private void SendString(string message)
{
try
{
byte[] data = Encoding.ASCII.GetBytes(message.ToString());
current.Send(data);
// current.BeginReceive(buffer, 0, BufferSize, SocketFlags.None, ReceiveCallback, current);
dataSent++;
}
catch (Exception ex)
{
Console.WriteLine("Client disconnected!" + ex.Message);
}
Console.WriteLine(dataSent);
}
}
internal sealed class Player
{
public Player(string newuser, string toString)
{
}
}
Client output
Port[default]: 100
Connection attempt to 127.0.0.1: 1 attempts
Connected!
Sent: newuser:6b06f0a6-bdb0-4471-ac58-fa9c490b7555
1
Sent: username:100|200
2
6b06f0a6-bdb0-4471-ac58-fa9c490b7555username:100|200 has joined the game.
Clients connected.
Sent: username:100|200
3
Server output
Setting up server...
Server setup complete
Listening on port: 100
Client connected: 127.0.0.1:1082
1
6b06f0a6-bdb0-4471-ac58-fa9c490b7555username:100|200 has joined the game.
username:100|200

Related

UDP Connection between two PC's (requested address is not valid)

first - my program works without any problems in a Network with a router. Now I need to establish a connection between two PC's with static IP's, but I get the following message: the requested address is not valid in its context.
Some connect code:
namespace ConsoleUdpTest
{
class Program
{
public static Socket socketReceiver;
public static Socket socketSender;
private const int bufSize = 8 * 1024;
private static State state = new State();
private static EndPoint epFrom = new IPEndPoint(IPAddress.Any, 0);
private static EndPoint epTo = new IPEndPoint(IPAddress.Any, 0);
private static AsyncCallback recv = null;
private static string udpBindingIp = "192.168.2.1";
private static int udpBindingPort = 27000;
private static string udpOutIp = "self";
private static int udpOutPort = 0;
static void Main(string[] args)
{
socketReceiver = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socketReceiver.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.ReuseAddress, true);
socketReceiver.Bind(new IPEndPoint(IPAddress.Parse(udpBindingIp), udpBindingPort));
socketSender = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socketSender.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.ReuseAddress, true);
Receive();
while (true)
{
System.Console.ReadKey();
};
}
private static void Send(string text)
{
try
{
socketSender.Connect(epTo);
byte[] data = Encoding.ASCII.GetBytes(text);
socketSender.BeginSend(data, 0, data.Length, SocketFlags.None, (ar) =>
{
State so = (State)ar.AsyncState;
int bytes = socketSender.EndSend(ar);
}, state);
}
catch (Exception e)
{
string s = e.Message;
}
}
private static void Receive()
{
socketReceiver.BeginReceiveFrom(state.buffer, 0, bufSize, SocketFlags.None, ref epFrom, recv = (ar) =>
{
try
{
State so = (State)ar.AsyncState;
int bytes = socketReceiver.EndReceiveFrom(ar, ref epFrom);
socketReceiver.BeginReceiveFrom(so.buffer, 0, bufSize, SocketFlags.None, ref epFrom, recv, so);
string message = Encoding.ASCII.GetString(so.buffer, 0, bytes);
if (udpOutIp.Contains("self"))
{
epTo = epFrom;
}
Send(message);
if (message.Contains("(") && message.Contains(")"))
{
Console.WriteLine("contains ( and )");
string command = message.TrimStart();
command = command.Substring(0, command.IndexOf("("));
string parameters = message.Substring(message.IndexOf("(") + 1, message.IndexOf(")") - message.IndexOf("(")-1);
//if (BleCommands.Exists(o => command.Contains(o)))
Console.WriteLine(command);
Console.WriteLine(parameters);
}
Console.WriteLine("in: " + message);
}
catch (Exception e)
{
string s = e.Message;
Console.WriteLine("Exception: " + s);
}
}, state);
}
public class State
{
public byte[] buffer = new byte[bufSize];
}
}
}
Server IP: 192.168.2.1 Subnetmask: 255.255.255.0
Client IP: 192.168.2.2 Subnetmask: 255.255.255.0
Ping the Server works without any problems

TcpClient connected but server not receiving message

Server :
public class TcpServer
{
private TcpListener tcpListener;
private static ManualResetEvent allDone = new ManualResetEvent(false);
public TcpServer(string url, int port)
{
tcpListener = new TcpListener(IPAddress.Parse(url), port);
pingMapper = new LightPingMapper();
}
public void Run()
{
tcpListener.Start();
Console.WriteLine("Server running");
while (true)
{
allDone.Reset();
tcpListener.BeginAcceptSocket(AcceptCallback, tcpListener);
Console.WriteLine("Accepting socket");
allDone.WaitOne();
}
Console.ReadLine();
}
private void AcceptCallback(IAsyncResult result)
{
try
{
allDone.Set();
var listener = (TcpListener) result.AsyncState;
var handler = listener.EndAcceptSocket(result);
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, state.buffer.Length, 0, ReadCallback, state);
}
catch (Exception e)
{
Console.WriteLine($"Error accepting callback. {e.Message}");
}
}
private void ReadCallback(IAsyncResult asyncResult)
{
try
{
string content = string.Empty;
Console.WriteLine("Read data from socket");
StateObject state = (StateObject) asyncResult.AsyncState;
Socket handler = state.workSocket;
int bytesRead = handler.EndReceive(asyncResult);
if (bytesRead > 0)
{
state.sb.Append(Encoding.UTF8.GetString(state.buffer));
content = state.sb.ToString();
Console.WriteLine(content + " " + DateTime.Now);
}
}
catch (Exception e)
{
Console.WriteLine($"Error reading socket. {e.Message}");
}
}
}
class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
Client:
public class TCPClientWrapper
{
private TcpClient tcpClient;
private readonly string address;
private readonly int port;
public TCPClientWrapper(string address, int port)
{
InitTcpClient();
this.address = address;
this.port = port;
}
public void SendMessage()
{
for(int i=0; i < 10; i++)
{
if (!SocketConnected())
{
TryConnect();
}
byte[] buffer = Encoding.UTF8.GetBytes("Hello");
tcpClient.Client.Send(buffer);
Thread.Sleep(60000);
}
}
private void TryConnect()
{
bool isConnected = false;
while (true)
{
try
{
InitTcpClient();
tcpClient.Connect(IPAddress.Parse(address), port);
if (SocketConnected())
{
Console.WriteLine("TcpClient, Connected");
isConnected = true;
break;
}
}
catch (Exception e)
{
Console.WriteLine("TcpClient, connection failed. Try to reconnect after 30 seconds, {0}", e.Message);
}
finally
{
if (!isConnected)
{
tcpClient.Close();
Thread.Sleep(30000);
}
}
}
}
private void InitTcpClient()
{
tcpClient = new TcpClient();
tcpClient.SendTimeout = 15;
}
private bool SocketConnected()
{
var s = tcpClient.Client;
if (!s.Connected)
return false;
bool part1 = s.Poll(1000, SelectMode.SelectRead);
bool part2 = s.Available == 0;
return !(part1 && part2);
}
}
The problem is that server read only first message , each next message is not received by server . The tcpClient is connected , but server doesn't receive any message . Could anyone suggest what is wrong with my code ?
In ReadCallback, you don't start the next read - so yes, your code only reads once.
Adding
handler.BeginReceive(state.buffer, 0, state.buffer.Length, 0, ReadCallback, state);
to the bottom of ReadCallback (when bytesRead > 0) should work. However! You aren't implementing proper framing, so you should be very cautious of that. A basic framing implementation for a text-based protocol (like this) would be to use some kind of line-end sentinel, and buffer data until you see a line-end, then process the line.
On TCP, you are only guaranteed to get the right bytes in the right order (or a failed socket eventually) - you are not guaranteed to get them in the same composition in terms of calls to Send exactly matching calls to Receive in terms of the numbers of bytes in each.

C# Socket Server communicates only locally

I need to make an application to return me the hours of all customers connected to the socket server.
But my application can only communicate locally.
Example:
If Endpoint Server is: (192.168.0.1, 32000)
Endpoint Client is: (192.168.0.1, 32000)
They connect and comunnicate.
But
If Endpoint Server is: (192.168.0.1, 32000)
Endpoint Client is: (192.168.0.2, 32000)
They connect, but not comunnicate.
Server Code:
class Server:Sincronia
{
GetIP getip = new GetIP();
private Socket _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private List<Socket> ListaDeClientesSockets = new List<Socket>(); /*Lista de sockets para adicionar clientes*/
private List<string> ListaDeClients = new List<string>();
private List<string> ListaDeHoras = new List<string>();
private const int _BUFFER_SIZE = 2048;
private int _PORT;
private string Ip;
private byte[] _buffer = new byte[_BUFFER_SIZE];
public Server(string IP, int port) /*Construtor para inicialização do IP e da Porta*/
{
this.Ip = IP;
this._PORT = port;
}
public void Connect()
{
Console.WriteLine("Socket Server ON");
Console.WriteLine(getip.getIP());
_serverSocket.Bind(new IPEndPoint(IPAddress.Parse(getip.getIP()), _PORT));
_serverSocket.Listen(5);
_serverSocket.BeginAccept(AcceptCallback, null);
}
public void ShowAllClients()
{
Console.WriteLine("####################### " + ListaDeClientesSockets.Count + " #######################");
for (int i = 0; i < ListaDeClientesSockets.Count; i++)
{
int j = i + 1;
Console.WriteLine("Client : " + j + " IP : " + ListaDeClients[i]);
}
}
private void CloseConnections()
{
foreach (Socket socket in ListaDeClientesSockets)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
_serverSocket.Close();
}
/// <summary>AcceptCallback método da classe Server
/// Evento realizado para aceitar conexões dos clientes adicionando em uma lista genérica
/// /// </summary>
private void AcceptCallback(IAsyncResult asyncronousResult)
{
Socket socket;
try
{
socket = _serverSocket.EndAccept(asyncronousResult);
}
catch (ObjectDisposedException)
{
return;
}
ListaDeClientesSockets.Add(socket);
ListaDeClients.Add(((IPEndPoint)socket.RemoteEndPoint).Address.ToString());
socket.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, socket);
Console.WriteLine("Client Connect " + ((IPEndPoint)socket.RemoteEndPoint).Address.ToString());
_serverSocket.BeginAccept(AcceptCallback, null);
}
public void SendToALL(string text)
{
foreach(Socket socket in ListaDeClientesSockets.ToList())
{
ListaDeHoras.Clear();
byte[] dataByte = Encoding.ASCII.GetBytes(text);
socket.Send(dataByte);
}
}
/// <summary>ReceiveCallBack método da classe Server
/// Evento realizado para receber e enviar dados do cliente através de um IASyncResult
/// </summary>
private void ReceiveCallback(IAsyncResult asyncronousResult)
{
Socket current = (Socket)asyncronousResult.AsyncState;
int received;
try
{
received = current.EndReceive(asyncronousResult);
}
catch (SocketException) /*Catch realizado caso houver perca de conexão com o cliente*/
{
Console.WriteLine("Conexão com o cliente " + ((IPEndPoint) current.RemoteEndPoint).Address.ToString() + " perdida.");
current.Close();
ListaDeClients.Remove(((IPEndPoint)current.RemoteEndPoint).Address.ToString());
ListaDeClientesSockets.Remove(current);
return;
}
byte[] recBuf = new byte[received];
Array.Copy(_buffer, recBuf, received);
string text = Encoding.ASCII.GetString(recBuf);
Console.WriteLine("Received Text: " + text);
ListaDeHoras.Add(text);
current.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
}
}
Program Server code:
class Program
{
static void Main(string[] args)
{
Console.Title = "Servidor";
Server server = new Server("localhost", 8000);
server.Connect();
while (true)
{
string text = Console.ReadLine();
if (text == "mostrar")
server.ShowAllClients();
else
server.SendToALL(text);
}
Console.ReadKey();
}
}
Client Code:
class Client
{
Socket socketClient;
static int port = 8000;
static string localhostIP = "127.0.0.1";
private const int _BUFFER_SIZE = 2048;
private byte[] _buffer = new byte[_BUFFER_SIZE];
private string IP;
public Client(string ip)
{
this.IP = ip;
}
public void Start()
{
IPEndPoint endp = new IPEndPoint(IPAddress.Parse(IP), port);
try
{
socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socketClient.BeginConnect(endp, new AsyncCallback(ConnectCALLBACK), socketClient);
Receive(socketClient);
}
catch
{
}
}
private void ConnectCALLBACK(IAsyncResult assynresult)
{
try
{
Socket client = (Socket)assynresult.AsyncState;
Console.WriteLine("Conectado");
client.EndConnect(assynresult);
}
catch(SocketException)
{
Console.WriteLine("Falta de conexão com o servidor, verifique sua conexão.");
}
}
public void Receive(Socket socket)
{
try
{
socket.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, socket);
}
catch
{
}
}
private void ReceiveCallback(IAsyncResult asyncronousResult)
{
Socket current = (Socket)asyncronousResult.AsyncState;
int received;
try
{
received = current.EndReceive(asyncronousResult);
}
catch (SocketException)
{
return;
}
byte[] recBuf = new byte[received];
Array.Copy(_buffer, recBuf, received);
string text = Encoding.ASCII.GetString(recBuf);
if(text == "clock")
{
string horas = DateTime.Now.ToString("dd-MM-yyyy HH:mm");
byte[] sended = Encoding.ASCII.GetBytes(horas);
current.Send(sended);
}
current.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
}
}
I need the server type "clock" and this is sent to all clients.
And so that clients receive, clients send to the server their respective hours.
just replace your client start function with the following
public void Start()
{
IPEndPoint endp = new IPEndPoint(IPAddress.Parse(IP), port);
try
{
socketClient = new Socket(endp, SocketType.Stream, ProtocolType.Tcp);
socketClient.BeginConnect(endp, new AsyncCallback(ConnectCALLBACK), socketClient);
Receive(socketClient);
}
catch
{
}
}

Tcp client send command toTcp Server to start x.exe and later server ignores client

I have created server and client everything worked just fine until I made 1 change. Created command start x.exe.
if(flag = Textmessage.ToLower() == "x.exe") //command from client
{
ProcessStartInfo _processStartInfo = new ProcessStartInfo();
_processStartInfo.WorkingDirectory = #"C:\Users\audrius\OneDrive\Programavimas\x\Bin\Debug\";
_processStartInfo.FileName = #"x.exe";
Process myProcess = Process.Start(_processStartInfo);
byte[] bytes = Encoding.ASCII.GetBytes("exe started");
socket.Send(bytes);//TELL client program started
ServerLogs.ServerLog("exe started");
Console.WriteLine("exe started");
return;
}
Everything works fine, I get response from server that program started. BUT then I want to send next command server don't accept it. Only then I restart client, server accept commands again. Why server freezes with this client?
My Client code:
namespace Multi_Client
{
class Program
{
private static readonly Socket _clientSocket = new Socket
(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private const int _PORT = 100;
static string name = "Client";
static void Main()
{
Console.WriteLine("Welcome {0}", name);
Console.Title = "Client";
ConnectToServer();
RequestLoop();
Exit();
}
private static void ConnectToServer()
{
int attempts = 0;
while (!_clientSocket.Connected)
{
try
{
attempts++;
Console.WriteLine("Connection attempt " + attempts);
_clientSocket.Connect(IPAddress.Loopback, _PORT);
}
catch (SocketException)
{
Console.SetCursorPosition(0, Console.CursorTop - 1);
Console.Write(new string(' ', Console.WindowWidth));
Console.SetCursorPosition(0, Console.CursorTop - 1);
}
}
// Console.Clear();
Console.WriteLine("Connected");
}
private static void RequestLoop()
{
Console.WriteLine(#"<Type ""exit"" to properly disconnect client>");
while (true)
{
SendRequest();
ReceiveResponse();
}
}
/// <summary>
/// Close socket and exit app
/// </summary>
private static void Exit()
{
SendString(name+ "exit"); // Tell the server we re exiting
_clientSocket.Shutdown(SocketShutdown.Both);
_clientSocket.Close();
System.Threading.Thread.Sleep(1000);
Environment.Exit(0);
}
private static void SendRequest()
{
Console.Write("Send a request: ");
string request = name + " "+ Console.ReadLine();
SendString(request);
System.Threading.Thread.Sleep(1000);
if (request.ToLower() == name +" exit")
{
Exit();
}
}
/// <summary>
/// Sends a string to the server with ASCII encoding
/// </summary>
private static void SendString(string text)
{
byte[] buffer = Encoding.ASCII.GetBytes(text);
_clientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None);
}
private static void ReceiveResponse()
{
if (_clientSocket.Connected)
{
var buffer = new byte[2048];
int received = _clientSocket.Receive(buffer, SocketFlags.None);
if (received == 0) return;
var data = new byte[received];
Array.Copy(buffer, data, received);
string text = Encoding.ASCII.GetString(data);
Console.WriteLine(text);
}
}
}
}
MY Server:
namespace Multi_Server
{
internal class Program
{
private static Socket _serverSocket;
private static readonly List<Socket> _clientSockets = new List<Socket> ();
private const int _BUFFER_SIZE = 2048;
private const int _PORT = 100;
private static readonly byte[] _buffer = new byte[1024];
private static void Main()
{
Console.Title = "Server";
Program.SetupServer();
Console.ReadLine();
Program.CloseAllSockets();
}
private static void SetupServer()
{
ServerLogs.ServerLog("Setting up server...");
Console.WriteLine("Setting up server...");
Program._serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Program._serverSocket.Bind(new IPEndPoint(IPAddress.Any, 100));
Program._serverSocket.Listen(5);
Program._serverSocket.BeginAccept(new AsyncCallback(Program.AcceptCallback), null);
Console.WriteLine("Server setup complete");
ServerLogs.ServerLog("Server setup complete");
}
private static void CloseAllSockets()
{
foreach (Socket socket in _clientSockets)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
_serverSocket.Close();
}
private static void AcceptCallback(IAsyncResult AR)
{
Socket socket;
try
{
socket = _serverSocket.EndAccept(AR);
}
catch (ObjectDisposedException)
{
return;
}
Program._clientSockets.Add(socket);
socket.BeginReceive(Program._buffer, 0, 1024, SocketFlags.None, new AsyncCallback(Program.ReceiveCallback), socket);
Console.WriteLine("Client connected, waiting for request...");
ServerLogs.ServerLog("Client connected, waiting for request...");
_serverSocket.BeginAccept(AcceptCallback, null);
}
private static void ReceiveCallback(IAsyncResult AR)
{
Socket socket = (Socket)AR.AsyncState;
int num;
try
{
num = socket.EndReceive(AR);
}
catch (SocketException)
{
Console.WriteLine("Client forcefully disconnected");
ServerLogs.ServerLog("Client forcefully disconnected");
socket.Close();
_clientSockets.Remove(socket);
return;
}
byte[] array = new byte[num];
Array.Copy(_buffer, array, num);
string RawText = Encoding.ASCII.GetString(array);
char[] textarray = RawText.ToCharArray();
int i = 0;
string name = "";
while (textarray[i] != ' ')
{
name += textarray[i];
i++;
}
string Textmessage = RawText.Substring(++i);
ServerLogs.ServerLog("Received from " + name + " !> Text: " + Textmessage);
Console.WriteLine("Received from {0} !> Text: {1}", name, Textmessage);
bool flag;
if(flag = Textmessage.ToLower() == "get time")
{
Console.WriteLine("Text is a get time request");
ServerLogs.ServerLog("Text is a get time request");
byte[] bytes = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
socket.Send(bytes);
ServerLogs.ServerLog("Time sent to client");
Console.WriteLine("Time sent to client");
}
else if(flag = Textmessage.ToLower() == "exit")
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
_clientSockets.Remove(socket);
ServerLogs.ServerLog("Client disconnected");
Console.WriteLine("Client disconnected");
return;
}
else if(flag = Textmessage.ToLower() == "x.exe") //command from client
{
ProcessStartInfo _processStartInfo = new ProcessStartInfo();
_processStartInfo.WorkingDirectory = #"C:\Users\audrius\OneDrive\Programavimas C#\Steambot Scrapper\Bin\Debug\";
_processStartInfo.FileName = #"x.exe";
Process myProcess = Process.Start(_processStartInfo);
byte[] bytes = Encoding.ASCII.GetBytes("exe started");
socket.Send(bytes);
ServerLogs.ServerLog("exe started");
Console.WriteLine("exe started");
return;
}
else
{
ServerLogs.ServerLog("Text is an invalid request");
Console.WriteLine("Text is an invalid request");
byte[] bytes = Encoding.ASCII.GetBytes("Invalid request");
socket.Send(bytes);
ServerLogs.ServerLog("Warning Sent");
Console.WriteLine("Warning Sent");
}
socket.BeginReceive(_buffer, 0, 1024, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
}
}
}//ServerLogs.cs >>>
class ServerLogs
{
private static string m_exePath = string.Empty;
public ServerLogs(string logMessage)
{
ServerLog(logMessage);
}
public static void ServerLog(string logMessage)
{
m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
try
{
using (StreamWriter w = File.AppendText(m_exePath + "\\" + "log.txt"))
{
Log(logMessage, w);
}
}
catch (Exception ex)
{
Console.WriteLine("Error: "+ex);
}
}
public static void Log(string logMessage, TextWriter txtWriter)
{
try
{
txtWriter.Write("\nLog Entry: ");
txtWriter.WriteLine("{0} {1} : {2}",
DateTime.Now.DayOfWeek, DateTime.Now.ToLongTimeString(), logMessage);
// txtWriter.WriteLine(" :");
// txtWriter.Write(" :{0}", logMessage);
// txtWriter.WriteLine("-------------------------------");
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex);
}
}
}
First of all (for future use), you are way better of using the TcpClient and TcpListener classes instead, they make things much easier.
Secondly, I see no meaning in the flag boolean. It's completely useless. If you need to check something just do if(Textmessage.ToLower() == "x.exe") as it already returns a bool.
Thirdly and finally, your server stops receiving due to that you don't make it start waiting for data again after a command has been processed. After you've processed a valid command you call return; which will stop your code from calling the socket.BeginReceive() method.
else if(flag = Textmessage.ToLower() == "x.exe") //command from client
{
...code...
return; //<-- Your problem.
}
You should remove every return; that you have in your ReceiveCallback method, EXCEPT for the one in the block where you disconnect, since the others are useless. Once an if or else if block successfully executes the other ones will be ignored - meaning that you do not have to terminate the method.
Removing the returns will make your
socket.BeginReceive(_buffer, 0, 1024, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
line always execute, thus meaning that the server will keep reading commands until the connection is terminated.

C# Creating chat rooms with multi client-server Sockets

Good afternoon, i've been trying to make a system kinda like skype in terms of convo groups, being able to enter a group and chatting with others that were online only within that group, issue is i dont know how i could separate this chat room into several ones and making them independent from each other with just one server
Overall, im trying to have multi chat rooms with one server while being able to save one's conversation chat log and be able to read it back
The current code i have works only as 1 general chat room
Server Side:
static void Main(string[] args)
{
Socket newSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Ip);
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 6000);
newSocket.Bind(endPoint);
newSocket.Listen(10);
Console.Write("Waiting...\n");
while (true)
{
Socket auxSocket = newSocket.Accept();
ThreadLab a = new ThreadLab(auxSocket);
Thread novaThread = new Thread(new ThreadStart(a.Connect));
novaThread.Start();
}
}
The ThreadLab Class:
private Socket socket;
static int nmrUsers = 0;
static int indice;
static Socket[] listaSockets = new Socket[10];
static ArrayList listaUtilizadores = new ArrayList();
public ThreadLab(Socket s)
{
socket = s;
listaSockets[indice++] = s;
}
public void Connect()
{
IPEndPoint aux = (IPEndPoint)socket.RemoteEndPoint;
Console.Write("Client " + aux.Address.ToString() + " connected\n");
}
And the client side that will have the reader and writer:
private static Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Ip);
private static ThreadStart tSReader;
private static ThreadStart tSWriter;
private static Thread tReader;
private static Thread tWriter;
private static string nome;
static void Main(string[] args)
{
IPEndPoint clientEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6000);
tSReader = new ThreadStart(reader);
tSWriter = new ThreadStart(writer);
tReader = new Thread(tSReader);
tWriter = new Thread(tSWriter);
try
{
client.Connect(clientEndPoint);
}
catch (SocketException e)
{
Console.WriteLine(e.ToString());
Console.ReadLine();
return;
}
tReader.Start();
tWriter.Start();
}
public static void writer()
{
string str;
byte[] data = new byte[1024];
nome = Console.ReadLine();
data = Encoding.ASCII.GetBytes(nome);
client.Send(data, data.Length, SocketFlags.None);
do
{
str = Console.ReadLine();
data = Encoding.ASCII.GetBytes(str);
client.Send(data, data.Length, SocketFlags.None);
} while (str != "exit");
client.Shutdown(SocketShutdown.Both);
tReader.Abort();
client.Close();
}
public static void reader()
{
byte[] data = new byte[1024];
int recv;
while (true)
{
try
{
recv = client.Receive(data);
}
catch (Exception e)
{
Console.WriteLine("Erro: " + e.Message);
Console.ReadLine();
break;
}
Console.WriteLine("\n" + Encoding.ASCII.GetString(data, 0, recv));
}
}
}
Someone can help me?

Categories