I have a problem with sending or receiving image (I don't know which part fails because my image is getting cutted on receive). I know that this kind of problem has much posts about it but any of these wasn't working for me.
So simply I have "my" socket server (not TCPClient). Server have to get screenshot of screen and send it to the client.
private static void ReceiveCallback(IAsyncResult AR)
{
Socket current = (Socket)AR.AsyncState;
int received;
IPEndPoint remoteIpEndPoint = current.RemoteEndPoint as IPEndPoint;
try
{
received = current.EndReceive(AR);
}
catch (SocketException)
{
current.Close();
return;
}
byte[] recBuf = new byte[received];
Array.Copy(buffer, recBuf, received);
string text = Encoding.ASCII.GetString(recBuf);
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.Write("Received Text: ");
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine(text);
if(text.ToLower() == "screenshot")
{
Image a = get_image.doscreen();
current.Send(ImageToByte(a));
}
if(current.Connected)
current.BeginReceive(buffer, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
}
I know that's not much code to show but I've done this server from tutorial and whole code it's pretty basic. Also I know that it might be buffer problem but I don't know how to fix this.
"My" client code:
private static void send()
{
try
{
string req = Console.ReadLine();
byte[] buffer = Encoding.ASCII.GetBytes(req);
_clientsocket.Send(buffer);
byte[] receivedbuf = new byte[1024];
int rec = _clientsocket.Receive(receivedbuf, receivedbuf.Length, SocketFlags.None);
byte[] data = new byte[rec];
Array.Copy(receivedbuf, data, rec);
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine(Encoding.ASCII.GetString(data));
if (req.ToLower() == "screenshot")
{
File.WriteAllBytes("test.png", data);
}
}
catch(Exception){
}
}
Related
So I am working on creating my own proxy server for my game server.
Whats happening so far is that I try to connect to my Terraria server and it says
Connecting..
Then I start my server application which accepts incoming requests on that specific IP & port and it prompts a MessageBox saying"Connected" and then the game goes from "Connecting..." to "Connecting to server..." but it gets stuck there, this is most likely because I am not redirecting the traffic from my proxy server to my server.. Right?
I've been trying to .Write() to the stream but I think I am writing to the wrong stream, do I write to the stream that accepts connections or do I create a new stream for outgoing traffic?
public partial class MainWindow : Window
{
public static IPAddress remoteAddress = IPAddress.Parse("127.0.0.1");
public TcpListener remoteServer = new TcpListener(remoteAddress, 7777);
public TcpClient client = default(TcpClient);
public TcpClient RemoteClient = new TcpClient("terraria.novux.ru", 7777);
public MainWindow()
{
InitializeComponent();
}
private void BtnListen_OnClick(object sender, RoutedEventArgs e)
{
if (StartServer())
{
client = remoteServer.AcceptTcpClient();
MessageBox.Show("Connected");
var receivedBuffer = new byte[1024];
//Should I write to this one instead?
var clientStream = client.GetStream();
var stream = RemoteClient.GetStream();
while (client.Connected)
if (client.Connected)
if (client.ReceiveBufferSize > 0)
{
receivedBuffer = new byte[1024];
stream.Write(receivedBuffer, 0, receivedBuffer.Length);
}
}
}
private bool StartServer()
{
try
{
remoteServer.Start();
MessageBox.Show("Server Started...");
return true;
}
catch (Exception exception)
{
MessageBox.Show(exception.ToString());
throw;
}
}
}
A simplified implementation could look like this.
public class Program
{
public static void Main(string[] args)
{
StartTcpListener("localhost", 9000);
}
private static byte[] SendReceiveRemoteServer(string host, int port, byte[] data)
{
try
{
// Create a TcpClient.
// Note, for this client to work you need to have a TcpServer
// connected to the same address as specified by the server, port
// combination.
var client = new TcpClient(host, port);
// Get a client stream for reading and writing.
// Stream stream = client.GetStream();
var stream = client.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent to server: {0}", Encoding.ASCII.GetString(data));
// Receive the TcpServer.response.
// Read the first batch of the TcpServer response bytes.
var bytes = new byte[256];
var allBytes = new List<byte>();
var i = stream.Read(bytes, 0, bytes.Length);
// Loop to receive all the data sent by the client.
while (i != 0)
{
allBytes.AddRange(bytes);
bytes = new Byte[256];
i = stream.DataAvailable ? stream.Read(bytes, 0, bytes.Length) : 0;
}
Console.WriteLine("Received from server: {0}", Encoding.ASCII.GetString(data));
// Close everything.
stream.Close();
client.Close();
return allBytes.ToArray();
}
catch (ArgumentNullException e)
{
Console.WriteLine("ArgumentNullException: {0}", e);
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
Console.WriteLine("\n Press Enter to continue...");
return new byte[0];
}
private static void StartTcpListener(string host, int port)
{
TcpListener server = null;
try
{
var ipHostInfo = Dns.GetHostEntry(host);
var ipAddress = ipHostInfo.AddressList[0];
// TcpListener server = new TcpListener(port);
server = new TcpListener(ipAddress, port);
// Start listening for client requests.
server.Start();
// Enter the listening loop.
while (true)
{
Console.WriteLine("Waiting for a connection... ");
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
var client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
// Get a stream object for reading and writing
var stream = client.GetStream();
// Buffer for reading data
var bytes = new Byte[256];
var allBytes = new List<byte>();
var i = stream.Read(bytes, 0, bytes.Length);
// Loop to receive all the data sent by the client.
while (i != 0)
{
allBytes.AddRange(bytes);
bytes = new Byte[256];
i = stream.DataAvailable ? stream.Read(bytes, 0, bytes.Length) : 0;
}
if (allBytes.Count > 0)
{
Console.WriteLine("Received from client: {0}", Encoding.ASCII.GetString(allBytes.ToArray()));
var received = SendReceiveRemoteServer("localhost", 11000, allBytes.ToArray());
// Send back a response.
stream.Write(received, 0, received.Length);
Console.WriteLine("Sent to client: {0}", Encoding.ASCII.GetString(received));
}
// Shutdown and end connection
client.Close();
}
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
finally
{
// Stop listening for new clients.
server.Stop();
}
Console.WriteLine("\nHit enter to continue...");
}
}
Although improvements should be made:
make it async
make it work with multiple TcpClients at the same time
I've been trying to send data from an android device to a computer by hosting a virtual network on the computer and connecting the android device to it (basically sending data over WLAN).
However, upon debugging the android app it always throws the following exception:
System.Net.Sockets.SocketException (0x80004005): Network subsystem is down.
Android App Code Snippet:
namespace TestWifiApp
{
[Activity(Label = "TestWifiApp", MainLauncher = true)]
public class MainActivity : Activity
{
string bssid = "00:18:39:12:2b:e9";
const string ssid = "TEST";
const string password = "123456abc";
const string kioskIp = "192.168.137.11";
const int kioskPort = 2201;
void sendData(string ntlId)
{
try {
System.Net.Sockets.Socket soc = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
System.Net.IPAddress ipAdd = System.Net.IPAddress.Parse(kioskIp);
System.Net.IPEndPoint ep = new System.Net.IPEndPoint(ipAdd, kioskPort);
soc.Connect(ep);
byte[] data = ASCIIEncoding.ASCII.GetBytes(ntlId);
soc.Send(data);
soc.Disconnect(false);
soc.Close();
Log.Debug("TEST", "Data sent");
}
catch(Exception ex)
{
Log.Debug("TEST",ex.ToString());
}
}
}
Server Code:
class Program
{
const int PORT_NO = 2201;
static Socket serverSocket;
static void Main(string[] args)
{
//---listen at the specified IP and port no.---
Console.WriteLine("Listening...");
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(new IPEndPoint(IPAddress.Any, PORT_NO));
serverSocket.Listen(4); //the maximum pending client, define as you wish
serverSocket.BeginAccept(new AsyncCallback(acceptCallback), null);
string result = "";
do
{
result = Console.ReadLine();
} while (result.ToLower().Trim() != "exit");
}
private const int BUFFER_SIZE = 4096;
private static byte[] buffer = new byte[BUFFER_SIZE]; //buffer size is limited to BUFFER_SIZE per message
private static void acceptCallback(IAsyncResult result)
{ //if the buffer is old, then there might already be something there...
Socket socket = null;
try
{
socket = serverSocket.EndAccept(result); // The objectDisposedException will come here... thus, it is to be expected!
//Do something as you see it needs on client acceptance
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket);
serverSocket.BeginAccept(new AsyncCallback(acceptCallback), null); //to receive another client
}
catch (Exception e)
{ // this exception will happen when "this" is be disposed...
//Do something here
Console.WriteLine(e.ToString());
}
}
const int MAX_RECEIVE_ATTEMPT = 10;
static int receiveAttempt = 0; //this is not fool proof, obviously, since actually you must have multiple of this for multiple clients, but for the sake of simplicity I put this
private static void receiveCallback(IAsyncResult result)
{
Socket socket = null;
try
{
socket = (Socket)result.AsyncState; //this is to get the sender
if (socket.Connected)
{ //simple checking
int received = socket.EndReceive(result);
if (received > 0)
{
byte[] data = new byte[received]; //the data is in the byte[] format, not string!
Buffer.BlockCopy(buffer, 0, data, 0, data.Length); //There are several way to do this according to https://stackoverflow.com/questions/5099604/any-faster-way-of-copying-arrays-in-c in general, System.Buffer.memcpyimpl is the fastest
//DO SOMETHING ON THE DATA int byte[]!! Yihaa!!
Console.WriteLine(Encoding.UTF8.GetString(data)); //Here I just print it, but you need to do something else
//Message retrieval part
//Suppose you only want to declare that you receive data from a client to that client
string msg = "I receive your message on: " + DateTime.Now;
socket.Send(Encoding.ASCII.GetBytes(msg)); //Note that you actually send data in byte[]
Console.WriteLine("I sent this message to the client: " + msg);
receiveAttempt = 0; //reset receive attempt
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket); //repeat beginReceive
}
else if (receiveAttempt < MAX_RECEIVE_ATTEMPT)
{ //fail but not exceeding max attempt, repeats
++receiveAttempt; //increase receive attempt;
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), socket); //repeat beginReceive
}
else
{ //completely fails!
Console.WriteLine("receiveCallback fails!"); //don't repeat beginReceive
receiveAttempt = 0; //reset this for the next connection
}
}
}
catch (Exception e)
{ // this exception will happen when "this" is be disposed...
Console.WriteLine("receiveCallback fails with exception! " + e.ToString());
}
}
}
I've tried connecting another computer to the hosted network and sending data to that computer, but the same exception is thrown.
First of all, what my Project should do if it would work:
Client written in C++ connects to Server coded in C#
When Connection was successfully, Client sends "0" to the Server to request a random String of Hexadecimals
If the Client recieved the Hexadecimals he will send "1" to the Server
Now the Client does some Stuff with the recieved Hexadecimalstring and then sends it back to the Server
if what the client did to the Hexadecimalstring was correct(Basic authing System) he returns "1" otherwise he returns "0"
Note: The recieving/sending on Client/Server side works, i tested it before by just sending 1 to the Server and the Server returns 0 if the recieved String was 1
Now to my Coding:
Thats the Server Part written in 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 = 11111;
private static byte[] buffer = new byte[100];
private void ReceiveCallback(IAsyncResult AR)
{
Socket current = (Socket)AR.AsyncState;
int received;
try
{
received = current.EndReceive(AR);
}
catch (SocketException)
{
Console.WriteLine("Client Disconnected! (Forced)");
current.Close();
clientSockets.Remove(current);
return;
}
//That's how my Example before worked:
/*byte[] recBuf = new byte[1];
Array.Copy(buffer, recBuf, received);
string text = Encoding.ASCII.GetString(recBuf);
if(text != "" && text.StartsWith("0"))
{
Console.WriteLine("Recieved: " + text);
string send = "1";
Console.WriteLine("Sending: " + send);
Byte[] data = ASCIIEncoding.ASCII.GetBytes(send);
current.Send(data);
Console.WriteLine("Sended!");
current.Shutdown(SocketShutdown.Both);
current.Close();
clientSockets.Remove(current);
Console.WriteLine("Client Disconnected!");
return;
}
current.BeginReceive(buffer, 0, 1, SocketFlags.None, ReceiveCallback, current);*/
//worked like a charm!
//That's my new Solution, that doesn't work:
byte[] recBuf = new byte[100];
Array.Copy(buffer, recBuf, received);
string text = Encoding.ASCII.GetString(recBuf);
while (text != "")
{
Console.WriteLine("Received Data: " + text);
if (text.StartsWith("0") && text.Length < 32)
{
Console.WriteLine("Client requests Random HexString...");
string rand = GetRandomHexNumber(32);
Byte[] data = ASCIIEncoding.ASCII.GetBytes(rand);
current.Send(data);
Console.WriteLine("Sended HexString! - " + rand);
}
if (text.StartsWith("1") && text.Length < 32)
{
Console.WriteLine("Client recieved the HexString!");
}
if (text.Length > 32 && !text.StartsWith("0") && !text.StartsWith("1"))
{
Console.WriteLine("Result recieved!");
//here will be some authing process but for simplicity just return "1"
byte[] data = ASCIIEncoding.ASCII.GetBytes("1");
current.Send(data);
current.Shutdown(SocketShutdown.Both);
current.Close();
clientSockets.Remove(current);
Console.WriteLine("Client Disconnected!");
return;
}
if (current.Connected)
current.BeginReceive(buffer, 0, 100, SocketFlags.None, ReceiveCallback, current);
}
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);
Console.WriteLine("Client Connected!");
serverSocket.BeginAccept(AcceptCallback, null);
}
private void setupServer()
{
serverSocket.Bind(new IPEndPoint(IPAddress.Any, PORT));
serverSocket.Listen(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();
}
setupServer(); gets launched on Console startup!
The C# part is the only problematic on the c++ side everything is fine!
I really hope somebody is able to help me now, since i didn't recieved any kind of help yet on this forum and i'm really in need for this to work and i'm sure here are plenty of programmers that could help me(maybe it's just a logical issue so every answer or comment is appreciated)
Thanks for your time :)
Replace
while (text != "")
{
// .....................
if (current.Connected)
current.BeginReceive(buffer, 0, 100, SocketFlags.None, ReceiveCallback, current);
}
if (current.Connected)
current.BeginReceive(buffer, 0, 100, SocketFlags.None, ReceiveCallback, current);
with
if (text != "")
{
// .....................
// Notice there's no BeginReceive() here!
}
if (current.Connected)
current.BeginReceive(buffer, 0, 100, SocketFlags.None, ReceiveCallback, current);
The function passed as callback paramater to BeginReceive() normally should not call BeginReceive() in a loop "until session is over". Instead it should call the BeginReceive() only once to pend another read operation if further data is expected (i.e. "session in not over").
I am trying to create a client/server application where a server sends commands to clients and clients send result back. The clients send data like this:
5|Hello
5 is the length of the string which is sent because then the server knows howmany characters it should receive before it should do something with that data. I tried to do that with this code:
private static void ReceiveCallback(IAsyncResult AR)
{
try
{
while (!Encoding.ASCII.GetString(_buffer).Contains("|"))
{
}
string[] a = Encoding.ASCII.GetString(_buffer).Split('|');
while (Encoding.ASCII.GetString(_buffer).Length < (Int32.Parse(a[0]) + a[0].Length + 1))
{
}
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);
if (!text.Contains("GET") && !text.Contains("HTTP") && text != null)
{
Console.WriteLine(DateTime.Now.ToString("h:mm:ss tt") + ":" + text);
}
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
}
catch
{
}
}
but this still does not give me the correct result. Also the CPU goes very high.
Picture of the result:
Can someone explain me why this happens? Thanks!
try to replace Encoding.ASCIIto Encoding.UTF8.
It can fix you issue.
Do note that you must to use the same encoding on both sides (sending and receiving data).
I hope it helps you.
have you tried using TcpClient? it can be way easier and gives you more control.
something like;
//make connection
NetworkStream stream = null;
socket = new TcpClient();
socket.Connect("192.168.12.12", 15879);
if (socket.Connected) {
stream = socket.GetStream();
}
//and than wait for tcp packets.
connectionThread = new Thread(ListenServer);
connectionThread.Start();
private void ListenToServer() {
Byte[] data = new Byte[1024];
String message = String.Empty;
Int32 dataLength = 0;
while (socket.Connected) {
try {
while (stream.DataAvailable) {
dataLength = stream.Read(data, 0, data.Length);
message = System.Text.Encoding.UTF8.GetString(data, 0, dataLength);
//do what ever you need here
Thread.Sleep(1);
}
} catch (Exception ex) {
}
Thread.Sleep(100);
}
moreover %1 cpu load!
I'm trying to make a proxy server with C#.
Here's my code:
static void Main(string[] args)
{
TcpListener server = null;
try
{
// Set the TcpListener on port 13000.
Int32 port = 13000;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);
// Start listening for client requests.
server.Start();
// Buffer for reading data
Byte[] bytes = new Byte[256];
String data = null;
WebRequest request;
WebResponse response;
// Enter the listening loop.
while (true)
{
Console.Write("Waiting for a connection... ");
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
data = null;
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream();
int i;
String[] input;
// Loop to receive all the data sent by the client.
while (stream.DataAvailable)
{
data = null;
i = stream.Read(bytes, 0, bytes.Length);
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine(String.Format("Received: {0}", data));
input = data.Split();
Console.WriteLine("\n\r\n input[1]" + input[1] + "\n");
Stream dataStream;
StreamReader reader;
string responseFromServer;
try
{
request = WebRequest.Create(input[1]);
response = request.GetResponse();
// Process the data sent by the client.
data = data.ToUpper();
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
reader = new StreamReader(dataStream);
// Read the content.
responseFromServer = reader.ReadToEnd();
// Display the content
Console.WriteLine(responseFromServer);
// Clean up the streams and the response.
byte[] msg = System.Text.Encoding.ASCII.GetBytes(responseFromServer);
// Send back a response.
stream.Write(msg, 0, msg.Length);
// Console.WriteLine("Sent: {0}", data);
//stream.Write();
reader.Close();
response.Close();
}
catch (System.UriFormatException e)
{
Console.WriteLine("Exception due to" + e.Data);
Console.WriteLine("Input[1] = " + input[1]);
}
data = null;
}
// Shutdown and end connection
client.Close();
}
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
finally
{
// Stop listening for new clients.
server.Stop();
}
Console.WriteLine("\nHit enter to continue...");
Console.Read();
}
It does not work for ssl requests but seems to work for http.
However, it does not load any images.
I'm using Firefox as the browser.
Any ideas why?
Also is this the best way to make a proxy server? Are there any other methods?
After a bit of testing, I wrote my own code.
using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Text;
namespace SharpProxy
{
class MainClass
{
private static void StartAcceptingClient(IAsyncResult ar)
{
var tcpClient = server.EndAcceptTcpClient(ar);
server.BeginAcceptTcpClient(new AsyncCallback(StartAcceptingClient), null);
// Read the data stream from the client.
NetworkStream stream = tcpClient.GetStream();
byte[] buffer = new byte[256];
Console.WriteLine("====== GOT A NEW TCP CLIENT ====== " + tcpClient.Client.RemoteEndPoint.ToString());
int read = stream.Read(buffer, 0, 1);
MemoryStream saved = new MemoryStream();
saved.Write(buffer, 0, read);
bool isValid = false;
while (read > 0 )
{
read = stream.Read(buffer, 0, 1);
saved.Write(buffer, 0, read);
//Check if the last four bytes were a double \r\n.
var aBytes = saved.ToArray();
int len = aBytes.Length;
if (aBytes.Length >= 4 && aBytes[len - 1] == '\n' && aBytes[len - 2] == '\r' && aBytes[len - 3] == '\n' && aBytes[len - 4] == '\r')
{
isValid = true;
break;
}
}
Console.WriteLine("End of receive.");
string originalRequest = Encoding.ASCII.GetString(saved.ToArray());
byte[] origBytes = saved.ToArray();
saved.Close();
Console.WriteLine(originalRequest);
if (!isValid)
{
Console.WriteLine("This wasn't a valid request");
return;
}
//Find the hoster and do our own request.
string host = originalRequest.Split(new char[] { '\n' }).First(line => line.StartsWith("Host:"));
host = host.Substring(5).Trim(); //Cut of rest.
Console.WriteLine("The host is: " + host);
//Do our own request.
try
{
Socket sProxy = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sProxy.Connect(host, 80);
sProxy.Send(origBytes);
//Now route everything between the tcpclient and this socket...
//create the state object
var state = new ProxyState() { ourSocket = sProxy, incomingClient = stream };
sProxy.BeginReceive(state.ReceiveBuffer, 0, state.ReceiveBuffer.Length, SocketFlags.None, new AsyncCallback(Receiver), state);
stream.BeginRead(state.SendBuffer, 0, state.SendBuffer.Length, new AsyncCallback(SendToHTTPServer), state);
}
catch (Exception) { Console.WriteLine("Exception while doing our own request"); }
}
static TcpListener server = null;
public static void Main(string[] args)
{
try
{
// Set the TcpListener on port 13000.
Int32 port = 13000;
IPAddress localAddr = IPAddress.Parse("0.0.0.0");
// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);
// Start listening for client requests.
server.Start();
Console.WriteLine("Server started on " + server.LocalEndpoint.ToString());
server.BeginAcceptTcpClient(new AsyncCallback(StartAcceptingClient), null);
while (true)
Thread.Sleep(10);
}
catch (Exception) { Console.WriteLine("Setting up the server failed"); }
}
private static void SendToHTTPServer(IAsyncResult ar)
{
try
{
ProxyState back = (ProxyState)ar.AsyncState;
int rec = back.incomingClient.EndRead(ar);
//Push this content to the server
back.ourSocket.Send(back.SendBuffer.Take(rec).ToArray());
back.incomingClient.BeginRead(back.SendBuffer, 0, back.SendBuffer.Length, new AsyncCallback(SendToHTTPServer), back);
}
catch (Exception e) { Console.WriteLine("Exc. when sending to server: " + e.ToString()); }
}
static void Receiver(IAsyncResult state)
{
try
{
ProxyState back = (ProxyState)state.AsyncState;
int rec = back.ourSocket.EndReceive(state);
//Set up the back and forth connections
back.incomingClient.Write(back.ReceiveBuffer, 0, rec);
back.ourSocket.BeginReceive(back.ReceiveBuffer, 0, back.ReceiveBuffer.Length, SocketFlags.None, new AsyncCallback(Receiver), back);
}
catch (Exception e) { Console.WriteLine("Exc. when receiving from client: " + e.ToString()); }
}
//Every proxy connection has an end an and a beginning, plus a
//Sending buffer and a receive buffer
class ProxyState
{
public NetworkStream incomingClient { get; set; }
public Socket ourSocket { get; set; }
private byte[] buffReceive = new byte[512];
private byte[] buffSend = new byte[512];
public byte[] ReceiveBuffer { get { return buffReceive; } set { buffReceive = value; } }
public byte[] SendBuffer { get { return buffSend; } set { buffSend = value; } }
}
}
}
Here's how it works: I listen on a port, and wait for a HTTP request. This is ended by a double carriage return and a linefeed, a \r\n\r\n. As soon as that happens, I try to parse the original host from the request with a Linq statement. I open my own socket to the server, and make use of the asynchronous callbacks. Basically, you need to write everything that comes from the proxy-iniator to the HTTP-Server, and everything that the HTTP-Server sends back needs to be pushed back to the original client aswell. This is why I set up my own state-object, which just saves the incomming client and the Socket, which is connected to the original HTTP server. And as such, communication can happen and I act as a proxy server.
Here's a screenshot with all the connections done right:
This proxy server is far from perfect, but the basic concept should be clear. This gave me some inspiration.
You use a streamreader on binary image data, that is not going to work. Not every binary is a valid ASCII encoded string. You should read the response as binary, and write it to the other stream as binary as well. You can try to convert it to ascii to print it to the console, but do not use the converted text to respond, because all the non-valid ascii characters will be converted to ?-s. I did modify your code to first read the response in a MemoryStream, and write that back. The data written to the console is still converted, but not user anywhere else.
static void Main(string[] args)
{
TcpListener server = null;
try
{
// Set the TcpListener on port 13000.
Int32 port = 13000;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);
// Start listening for client requests.
server.Start();
// Buffer for reading data
Byte[] bytes = new Byte[256];
String data = null;
WebRequest request;
WebResponse response;
// Enter the listening loop.
while (true)
{
Console.Write("Waiting for a connection... ");
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
data = null;
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream();
int i;
String[] input;
// Loop to receive all the data sent by the client.
while (stream.DataAvailable)
{
data = null;
i = stream.Read(bytes, 0, bytes.Length);
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine(String.Format("Received: {0}", data));
input = data.Split();
Console.WriteLine("\n\r\n input[1]" + input[1] + "\n");
Stream dataStream;
StreamReader reader;
string responseFromServer;
try
{
request = WebRequest.Create(input[1]);
response = request.GetResponse();
// Process the data sent by the client.
data = data.ToUpper();
dataStream = response.GetResponseStream();
MemoryStream ms = new MemoryStream();
dataStream.CopyTo(ms);
ms.Position = 0;
// Open the stream using a StreamReader for easy access.
reader = new StreamReader(ms);
// Read the content.
responseFromServer = reader.ReadToEnd();
// Display the content
Console.WriteLine(responseFromServer);
// Clean up the streams and the response.
byte[] msg = ms.ToArray();
// Send back a response.
stream.Write(msg, 0, msg.Length);
// Console.WriteLine("Sent: {0}", data);
//stream.Write();
reader.Close();
response.Close();
}
catch (System.UriFormatException e)
{
Console.WriteLine("Exception due to" + e.Data);
Console.WriteLine("Input[1] = " + input[1]);
}
data = null;
}
// Shutdown and end connection
client.Close();
}
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
finally
{
// Stop listening for new clients.
server.Stop();
}
Console.WriteLine("\nHit enter to continue...");
Console.Read();
}