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
{
}
}
Related
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
I was wondering how i can manage that my Socket Server, that listens on port 3333 and for any incoming IP Addresses can listen for external connections. On my local network it all works fine, but if people try to connect to the server from another router they cant connect, i already added a Exception for my Server.exe in the Firewall and opened the Port 3333 on my router. Is there anything else i have to do?
Any help is appreciated
EDIT:
Server Code(C#):
private static Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private static List<Socket> clientSockets = new List<Socket>();
private const int PORT = 3333;
private static byte[] buffer = new byte[100];
private static Random random = new Random();
private static int connectedClients = 0;
private void ReceiveCallback(IAsyncResult AR)
{
Socket current = (Socket)AR.AsyncState;
int received;
try
{
received = current.EndReceive(AR);
}
catch (SocketException)
{
Console.WriteLine("Client " + connectedClients + " Disconnected! (Forced)");
current.Close();
clientSockets.Remove(current);
return;
}
byte[] recBuf = new byte[100];
Array.Copy(buffer, recBuf, received);
string text = getText(Encoding.ASCII.GetString(recBuf));
if (text != "")
{
Console.WriteLine("Recieved: " + text);
}
if (current.Connected)
current.BeginReceive(buffer, 0, 100, SocketFlags.None, ReceiveCallback, current);
}
private void AcceptCallback(IAsyncResult AR)
{
Socket socket;
try
{
socket = serverSocket.EndAccept(AR);
}
catch (ObjectDisposedException)
{
return;
}
clientSockets.Add(socket);
socket.BeginReceive(buffer, 0, 100, SocketFlags.None, ReceiveCallback, socket);
connectedClients++;
Console.WriteLine("Client " + connectedClients + " Connected! [" + IPAddress.Parse(((IPEndPoint)socket.RemoteEndPoint).Address.ToString()) + "::" +
((IPEndPoint)socket.RemoteEndPoint).Port.ToString() + "]");
serverSocket.BeginAccept(AcceptCallback, null);
}
private void setupServer()
{
SocketPermission perm = new SocketPermission(NetworkAccess.Accept, TransportType.Tcp, ""/*Here would sit my IPv4*/, PORT);
perm.Assert();
serverSocket.Bind(new IPEndPoint(IPAddress.Any, PORT));
serverSocket.Listen(10);//0
Console.WriteLine("Server Started!");
Console.WriteLine("Listening for Clients...");
serverSocket.BeginAccept(AcceptCallback, null);
}
private void CloseAllSockets()
{
foreach (Socket socket in clientSockets)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
serverSocket.Close();
}
static void Main(string[] args)
{
Console.Title = "Server";
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.Green;
Program prgrm = new Program();
prgrm.setupServer();
Console.ReadLine();
prgrm.CloseAllSockets();
}
I have some clients that connect to the server at the same time, and each of them send to server a registration message.
So, the messages collide with previous messages when they come to the server.
How can I manage the communications without collision between the messages?
I use asynchronous tcp socket in C#.
Here the server:
class ServerSocket
{
//The ClientInfo structure holds the required information about every
//client connected to the server
struct ClientInfo
{
public Socket socket; //Socket of the client
public string strName; //Name by which the user logged into the chat room
}
//The collection of all clients logged into the room (an array of type ClientInfo)
ArrayList clientList;
//The main socket on which the server listens to the clients
Socket serverSocket;
byte[] byteData = new byte[5000];
const int NUM_CLIENT = 12;
public ServerSocket()
{
clientList = new ArrayList();
}
public void LoadServer()
{
try
{
//We are using TCP sockets
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//Assign the any IP of the machine and listen on port number 1000
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 1000);
//Bind and listen on the given address
serverSocket.Bind(ipEndPoint);
serverSocket.Listen(NUM_CLIENT);
//Accept the incoming clients
serverSocket.BeginAccept(new AsyncCallback(OnAccept), null);
Console.WriteLine("###################### S E R V E R ######################");
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private void OnAccept(IAsyncResult ar)
{
try
{
Socket clientSocket = serverSocket.EndAccept(ar);
//Start listening for more clients
serverSocket.BeginAccept(new AsyncCallback(OnAccept), null);
//Once the client connects then start receiving the commands from her
clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private void OnReceive(IAsyncResult ar)
{
string msgReceived = "";
try
{
Socket clientSocket = (Socket)ar.AsyncState;
clientSocket.EndReceive(ar);
msgReceived = GetString(byteData);
string strTemp = "";
for (int i = 0; i < msgReceived.IndexOf("<END>"); i++)
{
strTemp += msgReceived[i];
}
msgReceived = strTemp;
XmlBaseClientMsg xmlBaseClientMsg = new XmlBaseClientMsg();
BaseClientMsg baseClientMsgReceived = new BaseClientMsg();
baseClientMsgReceived = xmlBaseClientMsg.DeserializeFromString(msgReceived);
switch (baseClientMsgReceived.m_messageType)
{
case ClientMsgType.AI_REGISTRATION:
//When a user logs in to the server then we add him to our list of clients
ClientInfo AIClientInfo = new ClientInfo();
AIClientInfo.socket = clientSocket; // save the socket
AIClientInfo.strName = baseClientMsgReceived.m_sSenderID; // save the name of sender client
clientList.Add(AIClientInfo);
Console.WriteLine("The client: " + AIClientInfo.strName + " registered");
break;
case ClientMsgType.ENTITY_REGISTRATION:
//When a user logs in to the server then we add him to our list of clients
ClientInfo EntityClientInfo = new ClientInfo();
EntityClientInfo.socket = clientSocket; // save the socket
EntityClientInfo.strName = baseClientMsgReceived.m_sSenderID; // save the name of sender client
clientList.Add(EntityClientInfo);
Console.WriteLine("The client: " + EntityClientInfo.strName + " registered");
break;
#region
//case Command.Logout:
// //When a user wants to log out of the server then we search for her
// //in the list of clients and close the corresponding connection
// int nIndex = 0;
// foreach (ClientInfo client in clientList)
// {
// if (client.socket == clientSocket)
// {
// clientList.RemoveAt(nIndex);
// break;
// }
// ++nIndex;
// }
// clientSocket.Close();
// break;
#endregion
}
if (baseClientMsgReceived.m_messageType != ClientMsgType.AI_REGISTRATION)
{
Console.WriteLine("Type message: " + baseClientMsgReceived.m_messageType + " To: " +
baseClientMsgReceived.m_sReceiverID + " From: " + baseClientMsgReceived.m_sSenderID);
foreach (ClientInfo clientInfo in clientList)
{
if (clientInfo.strName == baseClientMsgReceived.m_sReceiverID)
{
byte[] message;
message = GetBytes(msgReceived);
// Send the message to reciever client
clientInfo.socket.BeginSend(message, 0, message.Length, SocketFlags.None,
new AsyncCallback(OnSend), clientInfo.socket);
Console.WriteLine("Msg No : " + baseClientMsgReceived.m_nMessageID + " Type: " + baseClientMsgReceived.m_messageType + " ==> has been sent");
break;
}
}
}
////If the user disconnects so no need to listen to him
// if (baseClientMsgReceived.m_messageType != ClientMsgType.Logout)
//{
//Start listening to the message send by the user
clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket);
//}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public void OnSend(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
client.EndSend(ar);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
static string GetString(byte[] bytes)
{
char[] chars = new char[bytes.Length / sizeof(char)];
System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
return new string(chars);
}
}
class Program
{
public static int Main( String[] args )
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.LoadServer();
while(true)
{
Console.ReadLine();
}
}
}
}
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
I'm connecting to my server on the internal network. But I cannot connect to a server on an external network. The server's firewall on the external network closed. The port forwarding server was.
Server side codes:
private byte[] _buffer = new byte[1024];
private List<Socket> _clientSockets = new List<Socket>();
private Socket _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public int PortNo;
private void SetupServer()
{
try
{
_serverSocket.Bind(new IPEndPoint(IPAddress.Any, PortNo));
_serverSocket.Listen(1);
_serverSocket.BeginAccept(new AsyncCallback(AcceptCallBack), null);
}
catch(Exception hata)
{
MessageBox.Show(hata.Message);
}
}
private void AcceptCallBack(IAsyncResult AR)
{
Socket socket = _serverSocket.EndAccept(AR);
_clientSockets.Add(socket);
try
{
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), socket);
_serverSocket.BeginAccept(new AsyncCallback(AcceptCallBack), null);
}
catch(Exception hata)
{
MessageBox.Show(hata.Message);
}
}
private void ReceiveCallBack(IAsyncResult AR)
{
Socket socket = (Socket)AR.AsyncState;
int received = socket.EndReceive(AR);
byte[] dataBuf = new byte[received];
Array.Copy(_buffer, dataBuf, received);
string text = Encoding.ASCII.GetString(dataBuf);
byte[] response = response = ekranGonderme();
try
{
socket.BeginSend(response, 0, response.Length, SocketFlags.None, new AsyncCallback(SendCallBack), null);
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), socket);
}
catch(Exception hata)
{
MessageBox.Show(hata.Message);
}
}
Client Side Codes:
private static Socket _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
int portNo = 20000;
IPAddress[] server_ip = Dns.GetHostAddresses(server's external ip address);
private void Form1_Load(object sender, EventArgs e)
{
LoopConnect();
LoopSendReceive()
}
private void LoopSendReceive()
{
try
{
byte[] buffer = Encoding.ASCII.GetBytes("ekran_iste");
_clientSocket.Send(buffer);
byte[] receiveBuf = new byte[999999];
int rec = _clientSocket.Receive(receiveBuf);
byte[] data = new byte[rec];
Array.Copy(receiveBuf, data, rec);
MemoryStream ms = new MemoryStream(data);
}
catch
{
}
}
private void LoopConnect()
{
int attempts = 0;
while (!_clientSocket.Connected)
{
try
{
attempts++;
_clientSocket.Connect(server_ip[0], portNo);
}
catch(SocketException)
{
}
}
}
}