I try to make communication between client / server .... In C # application as a client I send data to ESP serial monitor without problems, with the fact that I can only send data from the application to ESP. My request is how I send data from ESP server serial monitor
To C # application for example textbox
I tried some code examples, but I have a problem sending data from ESP server to C # application as client. Do you have any suggestions on how to solve my problem? Thank you for any reply. I attach codes.
ESP Server code:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
//const char* ssid = "KTEEM"; // Skola
//const char* password = "88888888"; // Skola
//const char* ssid = "Mi A3"; // Ja
//const char* password = "44114144"; // Ja
const char* ssid = "Slavo"; //Domov
const char* password = "bubo2222"; //Domov
//const char* host = "192.168.0.111"; //ipWifiSkola
//const char* host = "192.168.43.39"; //ipWifiMobil
const char* host = "192.168.0.105"; //ipWifiDomov
//const int udpPort = 8080; //portserver
int newData;
String data;
WiFiServer server(5045);
WiFiClient client;
void setup()
{
Serial.begin(115200);
wifiConnect();
server.begin();
}
void loop() {
if (WiFi.status() != WL_CONNECTED)
{
wifiConnect();
}
client = server.available();
if(Serial.available())
{
String command = Serial.readStringUntil('\n');
client.print(command);
delay(300);
}
if (client){
String data;
Serial.println("Client connected");
while (client.connected()){
while(client.available()>0)
{
//data = client.readStringUntil('\n');
//Serial.println(data);
char c = client.read();
Serial.write(c);
}
delay(10);
}
client.stop();
Serial.println("Client Disconnected");
}
}
void wifiConnect()
{
WiFi.begin(ssid, password);
Serial.println("");
while (WiFi.status () != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
C# client code:
using System;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.IO;
namespace TCPIP_ESP
{
class TCPClient
{
public int HostPort = 5045;
public string HostDomov = "192.168.0.105"; //Skola
public string HostMobil = "192.168.43.39"; //Mobil
public string HostSkola = "192.168.0.111"; //Domov
private TcpClient tcpClient = new TcpClient();
public Thread W_Thread;
public Thread R_Thread;
public bool IsListening = true;
NetworkStream networkStream = null;
public StreamReader serverData;
public StreamWriter clientData;
private StreamWriter streamWriter;
public NetworkStream NetworkStream { get => networkStream; set => networkStream = value; }
public void SendData(Client c)
{
if (NetworkStream.CanWrite)
{
byte[] sendBytes = Encoding.ASCII.GetBytes(c.txtMsg.Text + "$");
NetworkStream.Write(sendBytes, 0, sendBytes.Length);
c.txtMsg.Text = string.Empty;
NetworkStream.Flush();
}
else if (!NetworkStream.CanWrite)
{
Console.WriteLine("You can not read data from this stream");
tcpClient.Close();
}
}
public void ReadData(Client c)
{
try
{
string returnData = null;
byte[] bytes = new byte[4096];
if (NetworkStream.CanRead)
{
int bytesRead = NetworkStream.Read(bytes, 0, bytes.Length);
returnData = Encoding.UTF8.GetString(bytes, 0, bytesRead);
Console.WriteLine("Data read ..." + returnData);
tcpClient.Close();
NetworkStream.Close();
}
else
{
Console.WriteLine("You cannot read data from this stream.");
tcpClient.Close();
NetworkStream.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public void CreateConnection(Client c)
{
tcpClient.Connect(HostDomov, HostPort);
NetworkStream = tcpClient.GetStream();
streamWriter = new StreamWriter(NetworkStream);
c.lblChangeData.Text = "Client Socket Porgram - Server Connected ...";
tcpClient.ReceiveBufferSize = 1024;
tcpClient.SendBufferSize = 1024;
if (tcpClient.Connected)
{
c.checkBox1.BackColor = System.Drawing.Color.Green;
}
else
c.checkBox1.BackColor = System.Drawing.Color.Red;
}
public void Disconnect()
{
tcpClient.Dispose();
tcpClient.Close();
NetworkStream.Close();
}
public void msg(Client c, string mesg)
{
c.listBox_Receive.Text = c.txtMsg.Text + Environment.NewLine + " >> " + mesg;
}
}
}
Related
I'm making a simple chat application using TcpClient and TcpServer from System.Net.
I got everything working on my PC, the server communicates with the client and vice versa. But when I try to connect to the same server application using another PC (even on the same subnet as my PC) the thing doesn't work.
I've tried port-forwarding through my router, firewall and still nothing.
The Can you see me website says that the connection is being refused. Although!! Sometimes it says that the connection is timed out completely.
I am not sure what's wrong with my code or my PC, I would really appreciate some help from people that are more experienced in this area than I am.
Here is the configuration for the port forwarding in my router:
If you need the code for the client and the server, here they are:
P.S. I make the change to the client in the BeginConnect() part at the bottom in order to change the IP address that I'm connecting to
Client:
using System;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
namespace TcpTest_Client_
{
public partial class Form1 : Form
{
TcpClient client;
IPAddress localIP = null;
bool connected = false;
public Form1()
{
InitializeComponent();
}
public void clientConnectCallback(IAsyncResult result)
{
try
{
client.EndConnect(result);
Log("Connected to " + client.Client.RemoteEndPoint);
connected = true;
NetworkStream clientStream = client.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch (Exception ex)
{
//a socket error has occured
Log(ex.Message);
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
Log("Server on has disconnected");
break;
}
//message has successfully been received
UTF8Encoding encoder = new UTF8Encoding();
string bufferincmessage = encoder.GetString(message, 0, bytesRead);
Log("Server: " + bufferincmessage);
}
}
catch (Exception ex)
{
Log(ex.Message);
}
}
public void Log(string msg)
{
richTextBox1.BeginInvoke(new Action(
() =>
{
richTextBox1.Text += msg + "\n";
}));
}
private void Form1_Load(object sender, EventArgs e)
{
foreach (IPAddress addr in Dns.GetHostAddresses(Dns.GetHostName()))
{
if (addr.AddressFamily == AddressFamily.InterNetwork)
{
localIP = addr;
break;
}
}
client = new TcpClient(AddressFamily.InterNetwork);
}
private void button2_Click(object sender, EventArgs e)
{
try
{
client.BeginConnect(IPAddress.Parse("109.252.107.144"), 1234, clientConnectCallback, client);
}
catch (Exception ex)
{
Log(ex.Message);
}
}
private void button1_Click(object sender, EventArgs e)
{
if (connected)
{
UTF8Encoding encoder = new UTF8Encoding();
NetworkStream clientStream = client.GetStream();
byte[] stringToSend = new byte[richTextBox2.Text.Length];
stringToSend = encoder.GetBytes(richTextBox2.Text);
clientStream.Write(stringToSend, 0, stringToSend.Length);
}
}
}
}
Server:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace TcpTest
{
public partial class Form1 : Form
{
private TcpListener server;
private List<Thread> clientThreads = null;
public Thread MainThread;
public Form1()
{
InitializeComponent();
}
public void Log(string msg)
{
richTextBox1.BeginInvoke(new Action(
() =>
{
richTextBox1.Text += msg + "\n";
}));
}
public static string bufferincmessage;
public void AcceptSocketPackets(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch (Exception ex)
{
//a socket error has occured
Log(ex.Message);
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
Log("Client on " + tcpClient.Client.RemoteEndPoint + " has disconnected from the server");
break;
}
//message has successfully been received
UTF8Encoding encoder = new UTF8Encoding();
bufferincmessage = encoder.GetString(message, 0, bytesRead);
Log("Client from " + tcpClient.Client.RemoteEndPoint + ": " + bufferincmessage);
string stringToSend = "You sent me: " + bufferincmessage;
byte[] messageToSend = new byte[stringToSend.Length];
messageToSend = encoder.GetBytes(stringToSend);
clientStream.Write(messageToSend, 0, messageToSend.Length);
}
}
public void SocketAcceptCallback(IAsyncResult result)
{
TcpClient newClient = server.EndAcceptTcpClient(result);
Log("Accepted client on " + newClient.Client.RemoteEndPoint);
clientThreads.Add(new Thread(new ParameterizedThreadStart(AcceptSocketPackets)));
clientThreads[clientThreads.Count - 1].Start(newClient);
server.BeginAcceptTcpClient(SocketAcceptCallback, server);
}
private void Form1_Load(object sender, EventArgs e)
{
MainThread = Thread.CurrentThread;
clientThreads = new List<Thread>();
try
{
IPAddress localIP = null;
foreach (IPAddress addr in Dns.GetHostAddresses(Dns.GetHostName()))
{
if (addr.AddressFamily == AddressFamily.InterNetwork)
{
localIP = addr;
break;
}
}
localIP = IPAddress.Any;
// could also use this:
// server = new TcpListener(new IPEndPoint(IPAddress.Any, 1234));
server = new TcpListener(new IPEndPoint(localIP, 1234));
Log("Starting server on " + localIP + ":1234");
server.Start(6);
server.BeginAcceptTcpClient(SocketAcceptCallback, server);
Log("Started server on " + localIP + ":1234");
}
catch (Exception ex)
{
Log(ex.Message);
}
}
}
}
C++ is giving me problems like that. Try creating another project, paste the server code and build it as Release x86. If you change the build target and our problem is the same, windows firewall, even when turned off, won't allow the server or the client to run without any exception. If it doesn't work I might not know the answer.
I have a GPS Tracker Device, I have run a TCP/IP Server Code which Successfully establishes connection with each device in a separate Thread and Device Keep sending its heart beat after one minute and server replies ON. When I send a command to get device location it gives me location and everything is working fine.
Now I want to get location from an android device using web service, Now I'm confuse how can I use running thread of a specific device from an Android App?
class Server
{
TcpListener server = null;
public Server(string ip, int port)
{
IPAddress localAddr = IPAddress.Parse(ip);
server = new TcpListener(localAddr, port);
server.Start();
StartListener();
}
public void StartListener()
{
try
{
while (true)
{
Console.WriteLine("Waiting for a connection... ");
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
Thread t = new Thread(new ParameterizedThreadStart(HandleDeivce));
t.Start(client);
}
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
}
public void HandleDeivce(Object obj)
{
TcpClient client = (TcpClient)obj;
NetworkStream stream = client.GetStream();
string data = null;
Byte[] bytes = new Byte[256];
int i;
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
data = Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("{1}: Received: {0}", data, Thread.CurrentThread.ManagedThreadId);
if (data.StartsWith("##"))
{
data = "LOAD";
}
else
{
data = "ON";
}
byte[] msg = Encoding.ASCII.GetBytes(data);
stream.Write(msg, 0, msg.Length);
Console.WriteLine("{1}: Sent: {0}", data, Thread.CurrentThread.ManagedThreadId);
}
client.Close();
}
}
Try making code look like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace ConsoleApplication16
{
class Program
{
const string IP = "123.456.789.000";
const int PORT_NUMBER = 1234;
static AutoResetEvent autoEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
GPSClient client = new GPSClient(IP, PORT_NUMBER);
//start http client or equivalent here
while (true)
{
autoEvent.Reset();
autoEvent.WaitOne();
//wait for message from user/client on service port
string message = client.message;
//send message back to user/client
}
}
}
public class WebServer
{
}
public class GPSClient
{
const int BUFFER_SIZE = 256;
TcpClient client = null;
NetworkStream stream = null;
Byte[] bytes = new Byte[BUFFER_SIZE];
public string message { get; set; }
public GPSClient(string ip, int port)
{
try
{
Console.WriteLine("Connecting to Device... ");
client.Connect(ip, port);
Console.WriteLine("Connected!");
stream = client.GetStream();
stream.BeginRead(bytes, 0, BUFFER_SIZE, new AsyncCallback(HandleDeivce), stream);
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
}
public void HandleDeivce(IAsyncResult ar)
{
NetworkStream stream = ar.AsyncState as NetworkStream;
string data = null;
int i = stream.Read(bytes, 0, BUFFER_SIZE);
data = Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
message = data;
if (data.StartsWith("##"))
{
data = "LOAD";
}
else
{
data = "ON";
}
byte[] msg = Encoding.ASCII.GetBytes(data);
stream.Write(msg, 0, msg.Length);
Console.WriteLine("Sent: {0}", data);
stream.BeginRead(bytes, 0, BUFFER_SIZE, new AsyncCallback(HandleDeivce), stream);
}
}
}
I am creating a client application in C# for sending commands via telnet protocol to a remote router. Currently the remote router closes idle connections for 2~5 minutes. I am looking for a way to keep alive my connection.
I have tried following code:
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
but it doesn't work.
Here is my code for TelnetClient:
public class TelnetClient
{
private NetworkStream ns;
private Socket client;
private const string prompt = ">";
private const int buffer = 2048;
private string host;
private int port;
private string user;
private string password;
public TelnetClient(string host, int port, string user, string password)
{
client = new Socket(SocketType.Stream, ProtocolType.Tcp);
client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
this.host = host;
this.port = port;
this.user = user;
this.password = password;
}
public bool Connect()
{
try
{
client.Connect(host, port);
ns = new NetworkStream(client);
return true;
}
catch (Exception e)
{
Trace.TraceError(e.Message);
return false;
}
}
public bool Login()
{
Write(this.user);
ReadUntil(":", 1000);
Write(this.password);
if(ReadUntil(">", 1000) != null)
return true;
return false;
}
public string ReadUntil(string pattern, long timeout)
{
StringBuilder sb = new StringBuilder();
string text = "";
byte[] arr = new byte[buffer];
try
{
if (ns.CanRead)
{
Stopwatch s = new Stopwatch();
s.Start();
while (s.Elapsed < TimeSpan.FromMilliseconds(timeout))
{
text = sb.ToString().Trim().ToLower();
if (pattern.Length > 0 && text.ToLower().Trim().EndsWith(pattern))
{
return text.ToLower();
}
if (ns.DataAvailable)
{
int count = ns.Read(arr, 0, arr.Length);
sb.AppendFormat("{0}", Encoding.ASCII.GetString(arr, 0, count));
}
}
}
else
return null;
}
catch (Exception ex)
{
Trace.TraceError(ex.Message);
}
return null;
}
public void Write(string value)
{
byte[] arr = Encoding.ASCII.GetBytes(value + Environment.NewLine);
try
{
ns.Write(arr, 0, arr.Length);
ns.Flush();
System.Threading.Thread.Sleep(1000);
}
catch (Exception e)
{
Trace.TraceError(e.Message);
}
}
public string SendCommand(string cmd, int timeout)
{
Write(cmd);
return ReadUntil(prompt, timeout);
}
public void Disconnect()
{
try
{
byte[] arr = Encoding.ASCII.GetBytes("exit" + Environment.NewLine);
ns.Write(arr, 0, arr.Length);
ns.Close();
client.Close();
}
catch (Exception e)
{
Trace.TraceError(e.Message);
}
}
}
On one of my team's products, we found that the TCP keep-alive interval wasn't fired sufficiently often enough to keep the router port open for certain NATs.
We updated the protocol to send a "ping" message that was responded with a "pong" every 45 seconds. But that was for a protocol that we controlled.
For telnet, best bet would be to send the telnet escape character followed by a telnet command of NOP (241) or AYT (246) on every interval. See RFC 854 for more details.
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 worte a little Web Proxy program that uses a TcpListener, which listen on a specific port for web calls. Once it recieves a call it creates a socket, gets the header of the call, forwards it onto the web page requested, reads the response and returns it to the client doing the request. The proxy works lovely, but now I want to limit who has access to the net via the proxy by implimenting user names. How would I incorparate authentication onto my proxy?
Here is my code:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
namespace WebProxy2
{
public partial class Form1 : Form
{
public bool proxyOn = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
public void log(string logText)
{
Application.DoEvents();
textBox1.Text += logText + "\r\n";
StreamWriter sw = new StreamWriter(#"c:\proxyLog.txt",true);
sw.WriteLine(logText);
sw.Close();
Application.DoEvents();
}
class WebProxy2
{
Socket clientSocket;
Form1 proxyGui;
Byte[] read = new byte[1024];
Byte[] Buffer = null;
Encoding ASCII = Encoding.ASCII;
const string HTTP_VERSION = "HTTP/1.0";
const string CRLF = "\r\n";
Byte[] RecvBytes = new Byte[4096];
public WebProxy2(Socket socket, Form1 form)
{
this.clientSocket = socket;
this.proxyGui = form;
}
public void run()
{
Application.DoEvents();
String clientmessage = " ", sURL = " ";
int bytes = readmessage(read, ref clientSocket, ref clientmessage);
if (bytes == 0)
{
return;
}
int index1 = clientmessage.IndexOf(' ');
int index2 = clientmessage.IndexOf(' ', index1 + 1);
if ((index1 == -1) || (index2 == -1))
{
throw new IOException();
}
proxyGui.log("Connecting to Site: " + clientmessage.Substring(index1 + 1, index2 - index1));
proxyGui.log("Connection from " + clientSocket.RemoteEndPoint);
string part1 = clientmessage.Substring(index1 + 1, index2 - index1);
int index3 = part1.IndexOf('/', index1 + 8);
int index4 = part1.IndexOf(' ', index1 + 8);
int index5 = index4 - index3;
sURL = part1.Substring(index1 + 4, (part1.Length - index5) - 8);
try
{
IPHostEntry IPHost = Dns.Resolve(sURL);
proxyGui.log("Request resolved: " + IPHost.HostName);
string[] aliases = IPHost.Aliases;
IPAddress[] address = IPHost.AddressList;
proxyGui.log(address[0].ToString());
IPEndPoint sEndpoint = new IPEndPoint(address[0], 80);
Socket IPsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPsocket.Connect(sEndpoint);
if (IPsocket.Connected)
proxyGui.log("Socket connect OK");
string GET = clientmessage;
Byte[] ByteGet = ASCII.GetBytes(GET);
IPsocket.Send(ByteGet, ByteGet.Length, 0);
Int32 rBytes = IPsocket.Receive(RecvBytes, RecvBytes.Length, 0);
proxyGui.log("Recieved " + rBytes);
//Buffer = RecvBytes;
String strRetPage = null;
strRetPage = strRetPage + ASCII.GetString(RecvBytes, 0, rBytes);
while (rBytes > 0)
{
rBytes = IPsocket.Receive(RecvBytes, RecvBytes.Length, 0);
strRetPage = strRetPage + ASCII.GetString(RecvBytes, 0, rBytes);
}
IPsocket.Shutdown(SocketShutdown.Both);
IPsocket.Close();
sendmessage(clientSocket, strRetPage);
}
catch (Exception exc2)
{
proxyGui.log(exc2.ToString());
}
}
private int readmessage(byte[] ByteArray, ref Socket s, ref String clientmessage)
{
int bytes = s.Receive(ByteArray, 1024, 0);
string messagefromclient = Encoding.ASCII.GetString(ByteArray);
clientmessage = (String)messagefromclient;
return bytes;
}
private void sendmessage(Socket s, string message)
{
Buffer = new Byte[message.Length + 1];
int length = ASCII.GetBytes(message, 0, message.Length, Buffer, 0);
s.Send(Buffer, length, 0);
}
}
const int port = 8080;
TcpListener tcplistener = new TcpListener(port);
private void btnProxy_Click_1(object sender, EventArgs e)
{
proxyOn = true;
log("Listening on port " + port + " " + DateTime.Now.ToString());
tcplistener.Start();
while (proxyOn)
{
Application.DoEvents();
if (tcplistener.Pending())
{
Socket socket = tcplistener.AcceptSocket();
WebProxy2 webproxy = new WebProxy2(socket, this);
webproxy.run();
}
Application.DoEvents();
}
}
private void btnStop_Click_1(object sender, EventArgs e)
{
Application.DoEvents();
proxyOn = false;
tcplistener.Stop();
log("Proxy stopped !!! " + DateTime.Now.ToString());
Application.DoEvents();
}
}
}
It's not clear whether you've implemented your own HTTP proxy protocol (more or less a simple TCP redirection based on the Host header) or if you're using the standard HTTP proxy protocol.
If you go for the standard proxy (which is probably better, unless you have a good reason not to do so), you should be able to use the Proxy-Authenticate, Proxy-Authorization and Proxy-Authentication-Info headers instead of WWW-Authenticate, Authorization and Authentication-Info (respectively) for HTTP Basic or Digest authentication for example.