I need to implement HTTP protocol through TCP. I already had a TCP/IP client-server program which had been working absolutely fine.
Now, I have done some minor change in the source code so that it behaves as an HTTP client-server. But, unfortunately it stopped working.
The following code ...
public void Write(string str)
{
if (IsConnected)
{
byte[] strBytes = Encoding.UTF8.GetBytes(str);
byte[] lenBytes = BitConverter.GetBytes(strBytes.Length);
Array.Reverse(lenBytes);
writer.Write(lenBytes);
writer.Write(strBytes);
writer.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public string Read()
{
if (IsConnected)
{
byte[] lenBytes = reader.ReadBytes(4);
Array.Reverse(lenBytes);
int len = BitConverter.ToInt32(lenBytes, 0);
byte[] bytes = reader.ReadBytes(len);
string str = Encoding.UTF8.GetString(bytes);
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
is changed to:
public void Write(string str)
{
if (IsConnected)
{
byte[] send = Encoding.ASCII.GetBytes(str);
writer.Write(send);
writer.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public string Read()
{
if (IsConnected)
{
StreamReader sr = new StreamReader(stream);
string str = sr.ReadToEnd();
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
What is the issue here?
Detailed Source Code
The following class is used by both server program and client program.
modified:
namespace MyClientServer
{
public class ClientClass
{
private string Host { get; set; }
private int Port { get; set; }
private bool IsConnected = false;
public string ID { get; private set; }
public TcpClient Tcp { get; private set; }
NetworkStream stream;
private StreamReader sr;
private StreamWriter writer;
public ClientClass()
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
}
//constructor for server program.
public ClientClass(TcpListener listener)
{
Tcp = listener.AcceptTcpClient();
Host = ((IPEndPoint)Tcp.Client.RemoteEndPoint).Address.ToString();
Port = ((IPEndPoint)Tcp.Client.LocalEndPoint).Port;
IsConnected = true;
stream = Tcp.GetStream();
sr = new StreamReader(stream);
writer = new StreamWriter(stream);
ID = Read();
Console.WriteLine("Client [{0}] is now connected.", ID);
}
public bool Connect()
{
if (IsConnected == false)
{
Console.WriteLine("Client [{0}] is now connected.", ID);
IsConnected = true;
Tcp = new TcpClient(Host, Port);
stream = Tcp.GetStream();
sr = new StreamReader(stream);
writer = new StreamWriter(stream);
return true;
}
return false;
}
//constructor for client.
public ClientClass(string host, int port)
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
Host = host;
Port = port;
}
public void Write(string str)
{
if (IsConnected)
{
byte[] send = Encoding.ASCII.GetBytes(str);
writer.Write(send);
writer.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public string Read()
{
if (IsConnected)
{
StreamReader sr = new StreamReader(stream);
string str = sr.ReadToEnd();
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public void PrintID()
{
Console.WriteLine("Client ID = {0}", ID);
}
public void SendIdToServer()
{
this.Write(ID);
}
public bool Disconnect()
{
if (IsConnected)
{
if (Tcp != null)
{
Tcp.Close();
Tcp = null;
Console.WriteLine("\nClient [{0}] is now disconnected.", ID);
return true;
}
}
return false;
}
}
}
original:
namespace MyClientServer
{
public class ClientClass
{
private string Host { get; set; }
private int Port { get; set; }
private bool IsConnected = false;
public string ID { get; private set; }
public TcpClient Tcp { get; private set; }
private BinaryReader reader;
private BinaryWriter writer;
public ClientClass()
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
}
//constructor for server program.
public ClientClass(TcpListener listener)
{
Tcp = listener.AcceptTcpClient();
Host = ((IPEndPoint)Tcp.Client.RemoteEndPoint).Address.ToString();
Port = ((IPEndPoint)Tcp.Client.LocalEndPoint).Port;
IsConnected = true;
NetworkStream stream = Tcp.GetStream();
reader = new BinaryReader(stream);
writer = new BinaryWriter(stream);
ID = Read();
Console.WriteLine("Client [{0}] is now connected.", ID);
}
public bool Connect()
{
if (IsConnected == false)
{
Console.WriteLine("Client [{0}] is now connected.", ID);
IsConnected = true;
Tcp = new TcpClient(Host, Port);
NetworkStream stream = Tcp.GetStream();
reader = new BinaryReader(stream);
writer = new BinaryWriter(stream);
return true;
}
return false;
}
//constructor for client.
public ClientClass(string host, int port)
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
Host = host;
Port = port;
}
public void Write(string str)
{
if (IsConnected)
{
byte[] strBytes = Encoding.UTF8.GetBytes(str);
byte[] lenBytes = BitConverter.GetBytes(strBytes.Length);
Array.Reverse(lenBytes);
writer.Write(lenBytes);
writer.Write(strBytes);
writer.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public string Read()
{
if (IsConnected)
{
byte[] lenBytes = reader.ReadBytes(4);
Array.Reverse(lenBytes);
int len = BitConverter.ToInt32(lenBytes, 0);
byte[] bytes = reader.ReadBytes(len);
string str = Encoding.UTF8.GetString(bytes);
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public void PrintID()
{
Console.WriteLine("Client ID = {0}", ID);
}
public void SendIdToServer()
{
this.Write(ID);
}
public bool Disconnect()
{
if (IsConnected)
{
if (Tcp != null)
{
Tcp.Close();
Tcp = null;
Console.WriteLine("\nClient [{0}] is now disconnected.", ID);
return true;
}
}
return false;
}
}
}
I took the advice of #Jimi and also took a look at the source code from this link.
Now my source code looks like the following:
public string Read()
{
if (IsConnected)
{
byte[] buffer = new byte[Tcp.ReceiveBufferSize];//create a byte array
int bytesRead = stream.Read(buffer, 0, Tcp.ReceiveBufferSize);//read count
string str = Encoding.ASCII.GetString(buffer, 0, bytesRead);//convert to string
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public void Write(string str)
{
if (IsConnected)
{
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(str);
stream.Write(bytesToSend, 0, bytesToSend.Length);
stream.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
and, it is working fine.
Related
The following source code polls for incoming client connections.
class ServerForm : Form
{
//...
void PollIncomingClientConns(TcpListener listener)
{
listener.Start();
_keepPolling = true;
try
{
while (_keepPolling)
{
ClientClass client = new ClientClass(listener);
ClientDictionary.Add(client.ID, client);
SetStringToTextBox("Client [" + client.ID + "] is now connected.");
Thread thread = new Thread(delegate()
{
ReadFromClient(client);
});
thread.IsBackground = true;
thread.Start();
}
_tcplistener.Server.Close();
_tcplistener.Server.Dispose();
_tcplistener = null;
}
catch (Exception ex)
{
var inner = ex.InnerException as SocketException;
if (inner != null && inner.SocketErrorCode == SocketError.ConnectionReset)
{
SetStringToTextBox("Disconnected");
}
else
{
SetStringToTextBox(ex.Message);
}
listener.Stop();
}
}
void ReadFromClient(ClientClass client)
{
try
{
while (true)
{
string str = client.Read();
SetStringToTextBox("[" + client.ID + "] says: " + str);
switch (str)
{
// ... service client requests ...
// ... text messages ...
}
if (!client.Tcp.Connected)
{
SetStringToTextBox("[" + client.ID + "] is disconnected.");
client.Close();
break;
}
}
}
catch
{
client.Close();
}
}
// ...
}
In order to shut down the server, I am clicking, say, a button and setting _keepPolling to false.
But, on the client-side, I am finding that the client is still able to connect to the server. I.e. the server isn't shut down.
How can I solve this issue?
Relevant Source Code
The following is the client source code,
public class ClientClass
{
public string ID { get; private set; }
public string Host { get; set; }
public int Port { get; set; }
public TcpClient Tcp { get; private set; }
private BinaryReader reader;
private BinaryWriter writer;
/// <summary>
/// Creates a clienbt at the Client-end.
/// This requires Host and Post property to be set.
/// </summary>
public ClientClass()
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
}
/// <summary>
/// Creates a client at the Client-end.
/// </summary>
/// <param name="host"></param>
/// <param name="port"></param>
public ClientClass(string host, int port)
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
Host = host;
Port = port;
}
/// <summary>
/// creates a proxy-client at the Server-end.
/// </summary>
/// <param name="listener"></param>
public ClientClass(TcpListener listener)
{
Tcp = listener.AcceptTcpClient();
Host = ((IPEndPoint)Tcp.Client.RemoteEndPoint).Address.ToString();
Port = ((IPEndPoint)Tcp.Client.LocalEndPoint).Port;
NetworkStream stream = Tcp.GetStream();
reader = new BinaryReader(stream);
writer = new BinaryWriter(stream);
ID = Read();
}
/// <summary>
/// Connects the client to the server.
/// </summary>
/// <returns></returns>
public bool Connect()
{
bool is_connected = IsConnected();
if (!is_connected)
{
Tcp = new TcpClient(Host, Port);
NetworkStream stream = Tcp.GetStream();
reader = new BinaryReader(stream);
writer = new BinaryWriter(stream);
return true;
}
else if (is_connected)
{
return true;
}
else return false;
}
public bool IsConnected()
{
if (Tcp == null)
{
return false;
}
else
{
Socket s = Tcp.Client;
bool part1 = s.Poll(1000, SelectMode.SelectRead);
bool part2 = (s.Available == 0);
if ((part1 && part2) || !s.Connected)
return false;
else
return true;
}
}
public void Write(string str)
{
if (IsConnected())
{
byte[] strBytes = Encoding.UTF8.GetBytes(str);
byte[] lenBytes = BitConverter.GetBytes(strBytes.Length);
Array.Reverse(lenBytes);
writer.Write(lenBytes);
writer.Write(strBytes);
writer.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public string Read()
{
if (IsConnected())
{
byte[] lenBytes = reader.ReadBytes(4);
Array.Reverse(lenBytes);
int len = BitConverter.ToInt32(lenBytes, 0);
byte[] bytes = reader.ReadBytes(len);
string str = Encoding.UTF8.GetString(bytes);
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public void PrintID()
{
Console.WriteLine("Client ID = {0}", ID);
}
public void SendIdToServer()
{
this.Write(ID);
}
public bool Close()
{
if (IsConnected())
{
if (Tcp != null)
{
Tcp.Close();
Tcp = null;
return true;
}
}
return false;
}
}
Edit:
class ServerForm : Form
{
// ...
private void startToolStripMenuItem_Click(object sender, EventArgs e)
{
string ipAddress = Constants.LOCAL_HOST_IP;
int portNo = Constants.PORT_NO;
IPAddress ip = IPAddress.Parse(ipAddress);
_tcplistener = new TcpListener(ip, portNo);
// poll for clients in a 2nd thread
Thread thread = new Thread(delegate()
{
PollIncomingClientConns(_tcplistener);
});
thread.IsBackground = true;
thread.Start();
SetStringToTextBox("Server program started on address [" + ipAddress + ":" + portNo + "]");
startToolStripMenuItem.Enabled = false;
stopToolStripMenuItem.Enabled = true;
}
// ...
}
After some testing, calling _tcplistener.Stop(); is sufficient. Call it where you are setting _keepPolling to false
we Have A serverPC and more ClientPC
this system is about a server/client of CafeGame/GameNet .
My Problem: when server is Online And after that, the clients are connected all things is OK!
But When Client is Online And after that, the Server are connected We Have Problem.
An existing connection was forcibly closed by the remote host
Server Code
{
public Dictionary<string, ClientData> lstClients = new Dictionary<string, ClientData>();
private delegate void CommandReceivedEventHandler(DataPacket.DataPacket data, ClientData sender);
private event CommandReceivedEventHandler CommandReceived;
private void AcceptSocket(IAsyncResult ar)
{
TcpListener listener = (TcpListener)ar.AsyncState;
try
{
ClientData clientData = new ClientData(listener.EndAcceptSocket(ar));
int i = clientData.Socket.RemoteEndPoint.ToString().IndexOf(':');
string IPAddress = clientData.Socket.RemoteEndPoint.ToString().Substring(0, i);
clientData.IsConnected = true;
if (lstClients.ContainsKey(IPAddress))
{
lstClients.Remove(IPAddress);
lstClients.Add(IPAddress, clientData);
dicClientUserControl[IPAddress].clientData = null;
dicClientUserControl[IPAddress].clientData = clientData;
dicClientUserControl[IPAddress].clientData.IsConnected = true;
}
else
{
Dispatcher.Invoke((Action)(() =>{u = new PCu(clientData, this, 0);}));
clientData.IsOnline = false;
dicClientUserControl.Add(IPAddress, u);
lstClients.Add(IPAddress, clientData);
Dispatcher.Invoke((Action)(() => { WarpPanelClient.Children.Add(u); }));
}
clientData.Socket.BeginReceive(clientData.ReceiveBuffer, 0, clientData.ReceiveBuffer.Length, SocketFlags.None, new AsyncCallback(Receive), clientData);
listener.BeginAcceptSocket(AcceptSocket, listener);
}
catch (Exception ex)
{
listener.BeginAcceptSocket(AcceptSocket, listener);
}
}
private void Receive(IAsyncResult ar)
{
ClientData clientData = (ClientData)ar.AsyncState;
SocketError err;
int byteReceived = clientData.Socket.EndReceive(ar, out err);
if (err != SocketError.Success)
{
byteReceived = 0;
clientData.IsConnected = false;
clientData.IsOnline = false;
}
clientData.IsConnected = true;
DataPacket.DataPacket data = DataPacket.DataPacket.FromByte(clientData.ReceiveBuffer);
CommandReceived.Invoke(data, clientData);
try
{
clientData.Socket.BeginReceive(clientData.ReceiveBuffer, 0, clientData.ReceiveBuffer.Length, SocketFlags.None, new AsyncCallback(Receive), clientData);
}
catch (SocketException ex)
{
clientData.IsConnected = false;
clientData.IsOnline = false;
lstClients[clientData.AddressText] = clientData;
//dicClientUserControl[clientData.AddressText] = u;
}
catch (Exception ex)
{
}
}
private bool SendCMD(DataPacket.DataPacket data)
{
try
{
else if (clientData.IsConnected)
clientData.Socket.Send(data.ToBytes());//?? Crash
return (true);
}
catch (Exception ex)
{
//An existing connection was forcibly closed by the remote host
IS_CONNECTED(false);
return false;
}
}
}
Class in Server
public class ClientData
{
public byte[] ReceiveBuffer = new byte[10240];
DataPacket.DataPacket Data = new DataPacket.DataPacket();
bool isConnected;// Connected Or Not
bool isOnline = false;// Loged in Or Not
public Socket Socket { get; private set; }
public string NameClient { get; set; }
public int Ver { get; set; }
public int id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public ClientData(Socket socket)
{
this.Socket = socket;
int i = Socket.RemoteEndPoint.ToString().IndexOf(':');
AddressText = Socket.RemoteEndPoint.ToString().Substring(0, i);
}
}
Client Code
bool isConnected;
public bool Connect(IPAddress IP, int Port, string SystemName)
{
try
{
if (isConnected == false)
{
SocketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SocketClient.Connect(IP, Port);
isConnected = true;
return true;
}
else
return true;
}
catch (Exception ex)
{
if (!isConnected)
{
this.Dispatcher.Invoke((Action)(() =>
{
lblError.Text = "SERVER IS OFFLINE ... !\n" + ex.Message;
}));
return false;
}
else
return true;
}
}
where is the my problem ?
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 6 years ago.
Improve this question
I am working at a Network Program but when I testing the code I find out that my friends (they are not in my local network) cant connect to the server. Now I found out that port forwarding could be the probleme but I dont know how I can change my code, that my friends can connect (when port forwarding the problem is than how can I implement port forwarding in my code).
Here my Classes:
Server class:
static Socket listenerSocket;
static List<ClientData> clients;
static List<ClientName> clientNames;
static List<ClientName> clientReady;
private int port;
public Server(int port)
{
InitializeComponent();
this.port = port;
}
private void Server_Load(object sender, EventArgs e)
{
Start();
}
private void Start()
{
consoleList.Items.Add("Starting Server on " + Packet.GetIP4Address() + ":" + port);
listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clients = new List<ClientData>();
clientNames = new List<ClientName>();
clientReady = new List<ClientName>();
IPEndPoint point = new IPEndPoint(IPAddress.Parse(Packet.GetIP4Address()), port);
try
{
listenerSocket.Bind(point);
}
catch (Exception)
{
MessageBox.Show("Port ist schon benutzt!");
Close();
}
Thread listenThread = new Thread(ListenThread);
listenThread.Start();
}
static void ListenThread()
{
for (;;)
{
listenerSocket.Listen(0);
ClientData data = new ClientData(listenerSocket.Accept());
clients.Add(data);
}
}
public static void ResetReadyClientList()
{
ResetReadyClientList_Server();
}
private static void ResetReadyClientList_Server()
{
clientReady.Clear();
}
public static List<ClientName> GetReadyClientList()
{
return clientReady;
}
public static List<ClientName> GetClientList()
{
return clientNames;
}
public static void Data_IN(object cSocket)
{
Socket clientScoket = (Socket)cSocket;
byte[] buffer;
int readBytes;
for (;;)
{
buffer = new byte[clientScoket.SendBufferSize];
readBytes = clientScoket.Receive(buffer);
if(readBytes > 0)
{
Packet packet = new Packet(buffer);
DataManager(packet);
}
}
}
static List<String> packetsReceived = new List<string>();
static List<String> clientsHasDownloaded = new List<string>();
static String path;
public static void DataManager(Packet p)
{
switch (p.packetType)
{
case PacketType.OutWindow:
String name = GetName(p.senderID);
MessageBox.Show(name + " hat aus dem Fenster geklickt!");
break;
case PacketType.RegisterName:
ClientName cName = new ClientName(p.senderID, p.gData[0]);
clientNames.Add(cName);
break;
case PacketType.Answer:
String senderName = GetName(p.senderID);
String answer = p.gData[0];
MessageBox.Show("Spieler " + senderName + " hat " + answer + " getippt!");
ClientName c = new ClientName(p.senderID, GetName(p.senderID));
if (clientReady.Contains(c)) clientReady.Remove(c);
clientReady.Add(c);
break;
case PacketType.HasDownloaded:
clientsHasDownloaded.Add(p.senderID);
if (clientsHasDownloaded.Count == clients.Count)
{
SoundHostForm form = new SoundHostForm();
form.ShowDialog();
path = p.gData[0];
}
break;
}
}
static ClientData GetClientData(String id)
{
foreach (ClientData c in clients)
{
if(c.id == id)
{
return c;
}
}
return null;
}
public static void SendFileToAll(String path)
{
Thread t = new Thread(() => SendFile(path));
t.Start();
}
private static void SendFile(String path)
{
clientsHasDownloaded.Clear();
Uri downloadLink = FileTransfer.UploadFile(path);
Packet p = new Packet(PacketType.CanDownload, "server");
p.gData.Add(downloadLink.ToString());
foreach (ClientData data in clients)
{
data.clientSocket.Send(p.ToBytes());
}
}
public static void SendPacketToAll(Packet p)
{
foreach(ClientData data in clients)
{
data.clientSocket.Send(p.ToBytes());
}
}
static String GetName(String id)
{
foreach (ClientName c in clientNames)
{
if (c.id == id)
{
return c.name;
}
}
return null;
}
}
class ClientData
{
public Socket clientSocket;
public Thread clientThread;
public String id;
public ClientData()
{
id = Guid.NewGuid().ToString();
clientThread = new Thread(Server.Data_IN);
clientThread.Start(clientSocket);
SendRegisterationPacket();
}
public ClientData(Socket clientSocket)
{
this.clientSocket = clientSocket;
id = Guid.NewGuid().ToString();
clientThread = new Thread(Server.Data_IN);
clientThread.Start(clientSocket);
SendRegisterationPacket();
}
public void SendRegisterationPacket()
{
Packet p = new Packet(PacketType.Registration, "server");
p.gData.Add(id);
clientSocket.Send(p.ToBytes());
}
}
public class ClientName
{
public String id;
public String name;
public ClientName(String id, String name)
{
this.id = id;
this.name = name;
}
}
Client:
public static Socket master;
public string username;
public static string id;
private String ip;
private int port;
public Client(String username, String ipPortString)
{
InitializeComponent();
this.username = username;
ip = ipPortString.Split(':')[0];
port = Convert.ToInt32(ipPortString.Split(':')[1]);
}
private void Client_Load(object sender, EventArgs e){}
public void Start()
{
master = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint point = new IPEndPoint(IPAddress.Parse(ip), port);
try
{
master.Connect(point);
}
catch
{
MessageBox.Show("Fehler beim Verbinden! Code: 0x156f237" + "\n" + "Der Server konnte nicht gefunden werden!");
Thread.Sleep(1000);
Start();
}
Thread t = new Thread(Data_IN);
t.Start();
}
void Data_IN()
{
byte[] buffer;
int readBytes;
for (;;)
{
buffer = new byte[master.SendBufferSize];
readBytes = master.Receive(buffer);
if (readBytes > 0)
{
DataManager(new Packet(buffer));
}
}
}
static List<String> packetsReceived = new List<string>();
static TippForm tippFormCache;
void DataManager(Packet p)
{
PacketType type = p.packetType;
switch (type)
{
case PacketType.Registration:
id = p.gData[0];
Packet rp = new Packet(PacketType.RegisterName, id);
rp.gData.Add(username);
master.Send(rp.ToBytes());
break;
case PacketType.Window:
String windowID = p.gData[0];
if (windowID == ABCDForm.SERIALAZIE_ID)
{
if (p.senderID == "server")
{
if (!packetsReceived.Contains(p.packetID))
{
ABCDForm form = new ABCDForm(id, p.gData[1], p.gData[2], p.gData[3], p.gData[4], p.gData[5]);
if (!IsOpened(form))
{
form.ShowDialog();
packetsReceived.Add(p.packetID);
}
}
}
}
else if (windowID == OpenAnswerForm.SERIALIZE_ID)
{
if (p.senderID == "server")
{
if (!packetsReceived.Contains(p.packetID))
{
OpenAnswerForm form = new OpenAnswerForm(id, p.gData[1]);
if (!IsOpened(form))
{
form.ShowDialog();
packetsReceived.Add(p.packetID);
}
}
}
}
else if (windowID == TippForm.SERIALIZE_ID)
{
if (p.senderID == "server")
{
if (!packetsReceived.Contains(p.packetID))
{
tippFormCache = new TippForm(id, p.gData[1], p.gData[2], p.gData[3], p.gData[4], p.gData[5]);
if (!IsOpened(tippFormCache))
{
tippFormCache.ShowDialog();
packetsReceived.Add(p.packetID);
}
}
}
}
else if (windowID == SoundForm.SERIALAZIE_ID)
{
if (p.senderID == "server")
{
if (!packetsReceived.Contains(p.packetID))
{
SoundForm form = new SoundForm(id, p.gData[1]);
if (!IsOpened(form))
{
form.ShowDialog();
packetsReceived.Add(p.packetID);
}
}
}
}
else if (windowID == VideoPlayerForm.SERIALIZE_ID)
{
if (p.senderID == "server")
{
if (!packetsReceived.Contains(p.packetID))
{
playerForm = new VideoPlayerForm(id);
if (!IsOpened(playerForm))
{
Thread t = new Thread(() => OpenVideoPlayerWithSTA(p));
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
}
}
}
break;
case PacketType.OpenNewTipp:
if(tippFormCache != null)
{
tippFormCache.OpenNewTipp();
}
break;
case PacketType.CanDownload:
if(p.senderID == "server")
{
Uri downloadLink = new Uri(p.gData[0]);
String uri = FileTransfer.DownloadFile(downloadLink);
Packet replyPacket = new Packet(PacketType.HasDownloaded, id);
replyPacket.gData.Add(uri);
master.Send(replyPacket.ToBytes());
}
break;
case PacketType.Play:
if (IsOpened(playerForm))
{
playerForm.Start();
}
break;
case PacketType.TogglePause:
if (IsOpened(playerForm))
{
playerForm.Pause();
}
break;
case PacketType.Stop:
if (IsOpened(playerForm))
{
playerForm.Stop();
}
break;
}
}
private static void OpenVideoPlayerWithSTA(Packet p)
{
playerForm.ShowDialog();
packetsReceived.Add(p.packetID);
}
private static VideoPlayerForm playerForm;
private static bool IsOpened(Form form)
{
FormCollection fc = Application.OpenForms;
foreach(Form f in fc)
{
if(f == form)
{
return true;
}
}
return false;
}
And my Packet Class / Server Data:
[Serializable]
public class Packet
{
public List<String> gData;
public int packetInt;
public bool packetBool;
public string senderID;
public PacketType packetType;
public string packetID;
public Packet(PacketType packetType, string senderID)
{
gData = new List<String>();
this.senderID = senderID;
this.packetType = packetType;
packetID = Guid.NewGuid().ToString();
}
public Packet(byte[] bytes)
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream(bytes);
ms.Position = 0;
Packet p = (Packet)bf.Deserialize(ms);
ms.Close();
gData = p.gData;
packetBool = p.packetBool;
packetInt = p.packetInt;
packetType = p.packetType;
senderID = p.senderID;
packetID = Guid.NewGuid().ToString();
}
public byte[] ToBytes()
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
ms.Position = 0;
bf.Serialize(ms, this);
byte[] bytes = ms.ToArray();
ms.Close();
return bytes;
}
public static string GetIP4Address()
{
IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());
foreach(IPAddress ip in ips)
{
if(ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
return "127.0.0.1";
}
}
public enum PacketType
{
Registration,
Window,
/*[0] = FormID
*
* ABCD:
* [1] = Frage
* [2] = A
* [3] = B
* [4] = C
* [5] = D
*
* OPEN:
* [1] = Frage
*
* TIPP:
* [1] = 1. Tipp
* [2] = 2. Tipp
* [3] = 3. Tipp
* [4] = 4. Tipp
* [5] = 5. Tipp
*
* SOUND:
* [1] = Uri
*/
Answer,//[0] = Antwort
OutWindow,
RegisterName,
Play,
TogglePause,
Stop,
OpenNewTipp,
CanDownload,
HasDownloaded
}
I hope you can help me guys.
You activate port forwarding in the router/NAT that connects you to the Internet. Then your friends'clients should have your public IP address (the one of the router to the Internet Provider, you can see this address logging into the router/NAT) and should send the messages to a specific port. You go to the router and configure port forwarding. This assuming local network means your network is behind a router that connects you to the Internet.
I have following class take care the udp Sending
public static async Task SendStringUdpAsync(HostName remoteHost,
string remotePort, string message)
{
using (var socket = new DatagramSocket())
{
var stream = (await socket.GetOutputStreamAsync(
remoteHost, remotePort)).AsStreamForWrite();
using (var writer = new StreamWriter(stream))
{
await writer.WriteLineAsync(message.ToString());
await writer.FlushAsync();
}
}
}
But instead send a string, I want to send a custom class in udp
public class OSCString : IOSCValue<string>
{
static int PaddingLength = 4;
public string Contents { get; }
public char TypeTag { get { return 's'; }}
public byte[] Bytes { get; }
public OSCString(string contents)
{
Contents = contents;
Bytes = GetBytes();
}
public byte[] GetBytes()
{
byte[] bytes = new byte[GetByteLength()];
Encoding.ASCII.GetBytes(Contents, 0, Contents.Length, bytes, 0);
return bytes;
}
public int GetByteLength()
{
return GetPaddedLength(Contents.Length);
}
public static int GetPaddedLength(int length)
{
int terminatedLength = length + 1;
int paddedLength = (int)(Math.Ceiling(terminatedLength / (float)PaddingLength) * 4);
return paddedLength;
}
public static OSCString Parse(BinaryReader reader)
{
List<byte> bytes = new List<byte>();
byte current = reader.ReadByte();
while(current != 0)
{
bytes.Add(current);
current = reader.ReadByte();
}
string str = Encoding.ASCII.GetString(bytes.ToArray());
OSCString oscString = new OSCString(str);
int bytesToBurn = oscString.Bytes.Length - bytes.Count - 1;
for(int i = 0; i < bytesToBurn; i++)
{
reader.ReadByte();
}
return oscString;
}
}
I try DataWriter and StreamWrite, dont work too well.
The UWP take out the socket class, is there any Streamwrite can do the job?
I figure this out
var socket = new DatagramSocket();
//socket.MessageReceived += SocketOnMessageReceived;
using (var stream = await socket.GetOutputStreamAsync(remoteHost, remotePort))
{
using (var writer = new DataWriter(stream))
{
// var data = Encoding.UTF8.GetBytes(message);
writer.WriteBytes(packet.Bytes);
writer.StoreAsync();
}
}
Everything works great!!!!!!!!!
after a long search about reconnecting a client to a server (with a timer) I did find a way that works. well almost works.
Lets say I run 3 clients, when I shutdown the server and re-run it, only one client reconnect
seems like the problem is on the server's side, but can't figure it out.
here's my code (Base class only implements the INotifyPropertyChanged interface):
Client:
class RFClient : Base
{
public enum RFClientType { Sender, Receiver };
#region Properties
System.Threading.Timer _stTimer;
private int serverPort;
private string serverIP;
private string _name;
public string Name
{
get { return _name; }
set { _name = value; OnPropertyChanged("Name"); }
}
private string cType { get; set; }
private RFClientType _clientType;
public RFClientType ClientType
{
get { return _clientType; }
set
{
_clientType = value;
OnPropertyChanged("ClientType");
}
}
private TcpClient _tcpServer;
public TcpClient TcpServer
{
get { return _tcpServer; }
set { _tcpServer = value; OnPropertyChanged("TcpServer"); }
}
private string _msgRecieved;
public string MsgRecieved
{
get { return _msgRecieved; }
set { _msgRecieved = value; OnPropertyChanged("MsgRecieved"); }
}
private string _errorMSG;
public string ErrorMSG
{
get { return _errorMSG; }
set { _errorMSG = value; OnPropertyChanged("ErrorMSG"); }
}
#endregion
#region ctor
public RFClient(string IP, int Port, RFClientType clientType)
{
_name = Environment.UserName;
this._clientType = clientType;
if (_clientType == RFClientType.Receiver) { cType = "Receiver"; }
else if (_clientType == RFClientType.Sender) { cType = "Sender"; }
this._tcpServer = new TcpClient();
this.serverIP = IP;
this.serverPort = Port;
connectToserver(this._tcpServer, this.serverIP, this.serverPort);
}
#endregion
#region Methods
public void connectToserver(TcpClient tcpServer, string IP, int Port)
{
if (tcpServer != null)
{
try
{
_tcpServer.Connect(IP, Port);
SendMessage("onConnect");
ReadFromServer();
}
catch (Exception ex) { _errorMSG = ex.Message; }
}
}
public async void ReadFromServer()
{
string message;
if (_stTimer != null) { _stTimer.Dispose(); }
await Task.Run(() =>
{
while (true)
{
if (_tcpServer != null && !_tcpServer.Connected)
{
_stTimer = new System.Threading.Timer(Timer_Tick, null, 0, 15000);
break;
}
else
{
try
{
using (NetworkStream readStream = _tcpServer.GetStream())
{
byte[] bytes = new byte[256];
int i;
while ((i = readStream.Read(bytes, 0, bytes.Length)) != 0)
{
message = System.Text.Encoding.GetEncoding("Windows-1255").GetString(bytes, 0, i);
MsgRecieved = message;
}
}
}
catch (Exception ex) { _errorMSG = ex.Message; return; }
}
}
});
}
public async void SendMessage(string Message)
{
if (!_tcpServer.Connected)
{
_errorMSG = "No Connection";
return;
}
if (_tcpServer.Connected)
{
int msgSize;
await Task.Run(() =>
{
msgSize = Message.Length;
byte[] buffer = Encoding.GetEncoding("Windows-1255").GetBytes("$#1type" + cType + "$#2type" + "$#1name" + _name + "$#2name" + "$#1message" + Message + "$#2message");
NetworkStream serverStream = _tcpServer.GetStream();
serverStream.Write(buffer, 0, buffer.Length);
serverStream.Flush();
});
}
}
public void Close()
{
this._tcpServer.Close();
}
public void Timer_Tick(object sender)
{
_tcpServer.Close();
//_tcpServer = null;
_tcpServer = new TcpClient();
while (!_tcpServer.Connected)
{
try
{
connectToserver(_tcpServer, serverIP, serverPort);
break;
}
catch { ErrorMSG = "Cannot connect..."; }
}
}
#endregion
}
Server:
class RFServer : Base
{
#region Propertirs
private int myPort;
private TcpListener serverSocket;
public TcpListener ServerSocket
{
get { return serverSocket; }
set { serverSocket = value; OnPropertyChanged("ServerSocket"); }
}
private ObservableCollection<TcpClient> myclients;
public ObservableCollection<TcpClient> MyClients
{
get { return myclients; }
set { myclients = value; OnPropertyChanged("MyClients"); }
}
private string msgRecieved;
public string MsgRecieved
{
get { return msgRecieved; }
set { msgRecieved = value; OnPropertyChanged("MsgRecieved"); }
}
private string status;
public string Status
{
get { return status; }
set { status = value; OnPropertyChanged("Status"); }
}
private string errorStatus;
public string ErrorStatus
{
get { return errorStatus; }
set { errorStatus = value; OnPropertyChanged("ErrorStatus"); }
}
private string logPath = AppDomain.CurrentDomain.BaseDirectory + "serverRole.txt";
#endregion
#region ctor
public RFServer(IPAddress locallAddress, int Port)
{
this.myPort = Port;
try
{
if (!System.IO.File.Exists(logPath))
{
System.IO.File.Create(logPath).Close();
}
serverSocket = new TcpListener(locallAddress, this.myPort);
serverSocket.Start();
Status = "Server started";
writeLog(logPath, "Server started");
}
catch (Exception ex) { writeLog(logPath, ex.Message); ErrorStatus = ex.Message; }
}
#endregion
#region Methods
public async void ListenToClients()
{
await Task.Run(() =>
{
myclients = new ObservableCollection<TcpClient>();
TcpClient tcpClient = new TcpClient();
while (true)
{
try
{
tcpClient = serverSocket.AcceptTcpClient();
ReadClients(tcpClient);
}
catch (Exception ex) { tcpClient.Close(); writeLog(logPath, string.Format(ex.Message)); ErrorStatus = ex.Message; }
}
});
}
public async void ReadClients(TcpClient tcpClient)
{
string fullDataReceived, clientMessage, clientType, logStr;
string clientName = string.Empty;
await Task.Run(() =>
{
while (tcpClient.Connected)
{
try
{
NetworkStream networkStream = tcpClient.GetStream();
byte[] bytesFrom = new byte[10025];
networkStream.Read(bytesFrom, 0, (int)tcpClient.ReceiveBufferSize);
fullDataReceived = Encoding.GetEncoding("Windows-1255").GetString(bytesFrom);
clientMessage = GetSubstringByString("$#1message", "$#2message", fullDataReceived);
clientType = GetSubstringByString("$#1type", "$#2type", fullDataReceived);
clientName = GetSubstringByString("$#1name", "$#2name", fullDataReceived);
if (clientMessage == "onConnect")
{
logStr = string.Format("Client connected -- Name: {0}, Type: {1}, Message: {2}", clientName, clientType, clientMessage);
writeLog(logPath, logStr);
if (clientType == "Receiver")
{
myclients.Add(tcpClient);
}
networkStream.Flush();
}
else
{
logStr = string.Format("New message from {0}: {1}", clientName, clientMessage);
writeLog(logPath, logStr);
MsgRecieved = string.Format("{0}: {1}", clientName, clientMessage);
SendDataToClients(MsgRecieved);
}
}
catch (Exception ex)
{
if (string.IsNullOrWhiteSpace(clientName)) { clientName = "UnKnown"; }
ErrorStatus += ex.Message + Environment.NewLine;
tcpClient.Close();
writeLog(logPath, string.Format("cannot read from client: {0}{2}Error: {1}",clientName,ex.Message,Environment.NewLine));
}
}
});
}
public async void SendDataToClients(string message)
{
if (myclients.Count > 0)
{
byte[] buffer = Encoding.GetEncoding("Windows-1255").GetBytes(message);
NetworkStream clientStream;
string logStr;
for (int i = 0; i <= myclients.Count - 1; i++)
{
await Task.Run(() =>
{
if (((TcpClient)myclients[i]) != null && ((TcpClient)myclients[i]).Connected)
{
try
{
clientStream = ((TcpClient)myclients[i]).GetStream();
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
logStr = string.Format("Message Sent to {0} Clients. ({1})", myclients.Count, message);
writeLog(logPath, logStr);
Status += "Message Sent to " + myclients.Count + " Clients." + Environment.NewLine;
}
catch
{
((TcpClient)myclients[i]).Close();
myclients.RemoveAt(i);
writeLog(logPath, "client disconnected...");
ErrorStatus = "client disconnected..." + Environment.NewLine;
}
}
else
{
((TcpClient)myclients[i]).Close();
myclients.RemoveAt(i);
writeLog(logPath, "client disconnected...");
ErrorStatus += "client disconnected..." + Environment.NewLine;
}
});
}
}
}
/// <summary>
/// Trim a string between 2 delimiters (strings).
/// </summary>
/// <param name="startString">1st delimiter</param>
/// <param name="endString">2nd delimiter</param>
/// <param name="fullString">Full string</param>
/// <returns></returns>
public string GetSubstringByString(string startString, string endString, string fullString)
{
return fullString.Substring((fullString.IndexOf(startString) + startString.Length), (fullString.IndexOf(endString) - fullString.IndexOf(startString) - startString.Length));
}
public void writeLog(string filePath, string Logcontent)
{
File.AppendAllText(filePath, DateTime.Now + " :::: " + Logcontent + Environment.NewLine);
}
public void CloseServer()
{
writeLog(logPath, "Server Stopped");
this.serverSocket.Stop();
this.myclients.Clear();
}
#endregion
}
ReadClients() is working on a 3rd Thread, I think it should be on the same Thread as ListenToClients().