I keep getting the following exception when a client connects to the TCPListener.
Exception:
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at Test.Server.ProcessClient(Object client, Object clientId)
Server.cs
public class Server
{
private TcpListener tcpListener;
private Thread listenThread;
public event EventHandler<EventLogArgs> EventLog;
public Server()
{
// Startup Code
ThreadPool.SetMinThreads(50, 50);
}
void UpdateEventLog(EventLogArgs e)
{
if (EventLog != null)
{
EventLog(this, e);
}
}
public void Start(string ip, int port_num)
{
Globals.listen = true;
Int32 port = port_num;
IPAddress address = IPAddress.Parse(ip);
this.tcpListener = new TcpListener(address, port);
Socket listenerSocket = this.tcpListener.Server;
LingerOption lingerOption = new LingerOption(true, 10);
listenerSocket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.Linger,
lingerOption);
this.listenThread = new Thread(ListenForClients);
this.listenThread.Start();
UpdateEventLog(new EventLogArgs("Started server..."));
}
public void Stop()
{
Globals.listen = false;
UpdateEventLog(new EventLogArgs("Stop server request sent..."));
}
private void ListenForClients()
{
this.tcpListener.Start();
while (Globals.listen)
{
if (!this.tcpListener.Pending())
{
// This is so we can stop the server.
Thread.Sleep(25); // choose a number (in milliseconds) that makes sense
continue; // skip to next iteration of loop
}
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
Globals.clientRequests++;
int clientRequest = Globals.clientRequests;
UpdateEventLog(new EventLogArgs("(" + Globals.clientRequests + ") Client connected...\r\n"));
ThreadPool.QueueUserWorkItem(o => ProcessClient(client, clientRequest));
}
UpdateEventLog(new EventLogArgs("Stopped server!"));
this.tcpListener.Stop();
}
private void ProcessClient(object client, object clientId)
{
TcpClient tcpClient = (TcpClient)client;
int clientRequestId = (int)clientId;
NetworkStream clientStream = tcpClient.GetStream();
byte[] clientRequestRaw = new byte[1024];
int bytesRead;
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Process client request..."));
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(clientRequestRaw, 0, 512);
}
catch
{
//a socket error has occured
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") SOCKET ERROR\r\n\r\n" + e));
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Client disconnected from server, nothing sent."));
break;
}
//message has successfully been received.
ASCIIEncoding encoder = new ASCIIEncoding();
string clientRequest = encoder.GetString(clientRequestRaw, 0, bytesRead);
string[] cmd;
string success;
Dictionary<string, string> headers = new Dictionary<string, string>();
Dictionary<string, string> contents = new Dictionary<string, string>();
if (clientRequest.Length == 0)
{
return;
}
// Parse HTTP request
Parse Parse = new Parse();
Parse.HTTPRequest(clientRequest, out success, out cmd, out headers, out contents);
string response;
if (success == "TRUE")
{
response = "HTTP/1.1 200 OK\r\n\r\nHello World!\r\n";
}
else
{
response = "HTTP/1.1 200 OK\r\n\r\nHello Error!\r\n";
}
ResponseToClient(client, response);
clientStream.Close();
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Server response...\r\n\r\n" + response));
}
tcpClient.Close();
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Client disconnected."));
}
private void ResponseToClient(object client, string response)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(response);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
}
The Server class is started from the main thread like so:
this.server = new Server();
this.server.EventLog += new EventHandler<EventLogArgs>(UpdateEventLog);
ThreadPool.QueueUserWorkItem(o => this.server.Start("127.0.0.1", 3000));
What am I doing wrong here?
I have taken the while loop out from the ProcessClient() method and this seems to have fixed the problem. Thanks anyway.
private void ProcessClient(object client, object clientId)
{
TcpClient tcpClient = (TcpClient)client;
int clientRequestId = (int)clientId;
NetworkStream clientStream = tcpClient.GetStream();
byte[] clientRequestRaw = new byte[1024];
int bytesRead;
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Process client request..."));
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(clientRequestRaw, 0, 512);
}
catch (Exception e)
{
//a socket error has occured
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") SOCKET ERROR\r\n\r\n" + e));
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Client disconnected from server, nothing sent."));
break;
}
//message has successfully been received.
ASCIIEncoding encoder = new ASCIIEncoding();
string clientRequest = encoder.GetString(clientRequestRaw, 0, bytesRead);
string[] cmd;
string success;
Dictionary<string, string> headers = new Dictionary<string, string>();
Dictionary<string, string> contents = new Dictionary<string, string>();
if (clientRequest.Length == 0)
{
return;
}
// Parse HTTP request
Parse Parse = new Parse();
Parse.HTTPRequest(clientRequest, out success, out cmd, out headers, out contents);
string response;
if (success == "TRUE")
{
response = "HTTP/1.1 200 OK\r\n\r\nHello World!\r\n";
}
else
{
response = "HTTP/1.1 200 OK\r\n\r\nHello Error!\r\n";
}
ResponseToClient(client, response);
clientStream.Close();
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Server response...\r\n\r\n" + response));
}
tcpClient.Close();
UpdateEventLog(new EventLogArgs("(" + clientRequestId + ") Client disconnected."));
}
You have to give the network right service.
Write services.msc in run,then find your service.
YourService->Properties-> Log On-> Log On as Network
Since you solved your problem I'm just gonna give you two hints:
First of all, do not use the thread pool to make synchronous operations asynchronous. It's a waste of resources. Use the asynchronous methods instead (BeginAccept/EndAccept etc).
Next break your class into multiple classes. One taking care of the server parts only and one taking care of the client parts only. It makes your code a lot easier to follow (even for you :)).
Anyway don't use if (success == "TRUE")!
Related
I have a Winforms application that's going to transfers data to an Android application, for now it accepts a connection and displays a line of text as output. I tested on my local machine using the telnet command in PowerShell and it returns the correct message. When I tried the command from another PC on my network, it just times out and fails to connect. I made sure the port was free and that my firewall was turned off.
Here is my method:
public void senddata()
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
TcpListener server = null;
try
{
Int32 port = 4296;
IPAddress localAddr =IPAddress.Any;
server = new TcpListener(localAddr, port);
server.Start();
Byte[] bytes = new Byte[256];
while (true)
{
server.Start();
Debug.WriteLine("Waiting for a connection... ");
TcpClient client = server.AcceptTcpClient();
NetworkStream stream = client.GetStream();
Debug.WriteLine("Connected!");
server.Stop();
while (stream.Read(bytes, 0, bytes.Length) != 0)
{
string data = "CPU: " + cpuCircle.Value + " C" + " | GPU: " + gpuCircle.Value + " C";
byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
stream.Write(msg, 0, msg.Length);
stream.Flush();
}
client.Close();
}
}
catch (SocketException m)
{
Debug.WriteLine("SocketException: "+m);
}
finally
{
server.Stop();
}
}).Start();
}
Any idea what I'm doing wrong?
I think the main issue is that your listener object is being created in Thread itself due to which only first client able to connect. Please make TcpListener object before calling senddata() method and this listener should accept connection before calling senddata() method as well and pass client object to senddata(TcpClient client) method. By doing so you would be able to entertain theoretically unlimited clients simultanously:
Try This:
void StackOverflow4() // Your calling method
{
TcpListener server = null;
Int32 port = 4296;
IPAddress localAddr = IPAddress.Any;
try
{
server = new TcpListener(localAddr, port);
server.Start();
Byte[] bytes = new Byte[256];
while (true)
{
Debug.WriteLine("Waiting for a connection... ");
TcpClient client = server.AcceptTcpClient();
senddata(client);
}
}
catch (SocketException m)
{
Debug.WriteLine("SocketException: " + m);
//Some logic to restart listner
}
catch(Exception ex)
{
Debug.WriteLine(ex.Message);
//Some logic to restart listner
}
}
public void senddata(TcpClient client)
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
try
{
Byte[] bytes = new Byte[256];
while (true)
{
NetworkStream stream = client.GetStream();
Debug.WriteLine("Connected!");
//server.Stop();
while (stream.Read(bytes, 0, bytes.Length) != 0)
{
string data = "CPU: " + cpuCircle.Value + " C" + " | GPU: " + gpuCircle.Value + " C";
byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
stream.Write(msg, 0, msg.Length);
stream.Flush();
}
client.Close();
}
}
catch (SocketException m)
{
Debug.WriteLine("SocketException: " + m);
}
finally
{
//server.Stop();
}
}).Start();
}
All i want to do is send message to client from server. I try a lot of tutorial etc. but still can't send message from server to client.
Send from client to server is simple and have it in code. When client Send "HI" to server i want to respond Hi to client. But dunno what should i add to my code. Can someone help me with that? Please don't do it like duplicate i know there is a lot of similar topic but can't find solution.
Server code:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
IPAddress ip = Dns.GetHostEntry("localhost").AddressList[0];
TcpListener server = new TcpListener(ip, Convert.ToInt32(8555));
TcpClient client = default(TcpClient);
try
{
server.Start();
Console.WriteLine("Server started...");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
};
while (true)
{
client = server.AcceptTcpClient();
byte[] receivetBuffer = new byte[100];
NetworkStream stream = client.GetStream();
stream.Read(receivetBuffer, 0, receivetBuffer.Length);
StringBuilder msg = new StringBuilder();
foreach(byte b in receivetBuffer)
{
if (b.Equals(59))
{
break;
}
else
{
msg.Append(Convert.ToChar(b).ToString());
}
}
////Resive message :
if (msg.ToString() =="HI")
{
///#EDIT 1
///// HERE Is SENDING MESSAGE TO CLIENT//////////
int byteCount = Encoding.ASCII.GetByteCount("You said HI" + 1);
byte[] sendData = new byte[byteCount];
sendData = Encoding.ASCII.GetBytes("You said HI" + ";");
stream.Write(sendData, 0, sendData.Length);
}
}
Client code:
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
try
{
string serverIP = "localhost";
int port = Convert.ToInt32(8555);
TcpClient client = new TcpClient(serverIP, port);
int byteCount = Encoding.ASCII.GetByteCount("HI"+ 1);
byte[] sendData = new byte[byteCount];
sendData = Encoding.ASCII.GetBytes("HI" + ";");
NetworkStream stream = client.GetStream();
stream.Write(sendData, 0, sendData.Length);
///////////////////////////////HERE I WANT A read message from server/
/////////////////////////////////////////////////////////////////////
stream.Close();
client.Close();
}
catch(Exception ex)
{
ex.ToString();
}
}
Try this Here is my version of client and server ,feel free to ask if any reference problem ,the client wait for server to (online) then if server is online connect with it.
Method to Connect with Server
private void Connectwithserver(ref TcpClient client)
{
try
{
//this is server ip and server listen port
server = new TcpClient("192.168.100.7", 8080);
}
catch (SocketException ex)
{
//exceptionsobj.WriteException(ex);
Thread.Sleep(TimeSpan.FromSeconds(10));
RunBoTClient();
}
}
byte[] data = new byte[1024];
string stringData;
TcpClient client;
private void RunClient()
{
NetworkStream ns;
Connectwithserver(ref client);
while (true)
{
ns = client.GetStream();
//old
// ns.ReadTimeout = 50000;
//old
ns.ReadTimeout = 50000;
ns.WriteTimeout = 50000;
int recv = default(int);
try
{
recv = ns.Read(data, 0, data.Length);
}
catch (Exception ex)
{
//exceptionsobj.WriteException(ex);
Thread.Sleep(TimeSpan.FromSeconds(10));
//try to reconnect if server not respond
RunClient();
}
//READ SERVER RESPONSE/MESSAGE
stringData = Encoding.ASCII.GetString(data, 0, recv);
}
}
Server
IPAddress localAdd = IPAddress.Parse(SERVER_IP);
TcpListener listener = new TcpListener(localAdd, PORT_NO);
Console.WriteLine("Listening...");
listener.Start();
while (true)
{
//---incoming client connected---
TcpClient client = listener.AcceptTcpClient();
//---get the incoming data through a network stream---
NetworkStream nwStream = client.GetStream();
byte[] buffer = new byte[client.ReceiveBufferSize];
//---read incoming stream---
int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize);
//---convert the data received into a string---
string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine("Received : " + dataReceived);
//IF YOU WANT TO WRITE BACK TO CLIENT USE
string yourmessage = console.ReadLine();
Byte[] sendBytes = Encoding.ASCII.GetBytes(yourmessage);
//---write back the text to the client---
Console.WriteLine("Sending back : " + yourmessage );
nwStream.Write(sendBytes, 0, sendBytes.Length);
client.Close();
}
listener.Stop();
I want to make a simple client-server application. The server waits for connection from clients. The client can send various queries (short strings of less than 100 char) to the server and the server should respond to these queries by sending strings or files.
I found code online that uses a tcpListener.AcceptSocket() and I can send and receive strings from server and code that uses tcpListener.AcceptTcpClient() and I can send files to a different server program.
Below there is a function for sending files via TcpIP and one for sending strings via TcpIP. How should the server code look like, to acommodate both functions? The server is a console program.
public void SendFileViaTCP(string sFile, string sIPAddress, int portNo)
{
byte[] sendingBuffer = null;
TcpClient client = null;
toolStripStatusLabel1.Text = "";
lbConnect.Items.Clear();
progressBar1.Value = 0;
Application.DoEvents();
NetworkStream networkStream = null;
int bufferSize = 5000;
string checksum = CalculateMD5(sFile);
lbConnect.Items.Add("File " + sFile + " checksum = " + checksum);
try
{
client = new TcpClient(sIPAddress, portNo);
toolStripStatusLabel1.Text = "Connected to the Server...\n";
networkStream = client.GetStream();
FileStream fileStream = new FileStream(sFile, FileMode.Open, FileAccess.Read);
long fsLength = fileStream.Length;
int nPackets = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(fsLength) / Convert.ToDouble(bufferSize)));
progressBar1.Maximum = nPackets;
Application.DoEvents();
int currentPacketLength;
for (int i = 0; i < nPackets; i++) {
if (fsLength > bufferSize) {
currentPacketLength = bufferSize;
fsLength -= currentPacketLength;
Application.DoEvents();
}
else {
currentPacketLength = Convert.ToInt32(fsLength);
}
sendingBuffer = new byte[currentPacketLength];
fileStream.Read(sendingBuffer, 0, currentPacketLength);
networkStream.Write(sendingBuffer, 0, (int)sendingBuffer.Length);
progressBar1.PerformStep();
Application.DoEvents();
}
toolStripStatusLabel1.Text = "Sent " + fileStream.Length.ToString() + " bytes to the server";
fileStream.Close();
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
finally {
networkStream.Close();
client.Close();
}
}
void SendString(string str, string sIPAddress, int portNo)
{
try {
TcpClient tcpClient = new TcpClient();
lbConnect.Items.Add("Connecting...");
Application.DoEvents();
// use the ipaddress as in the server program
var tsk = tcpClient.ConnectAsync(sIPAddress, portNo);
tsk.Wait(3000); // here we set how long we want to wait before deciding the server is not responding.
lbConnect.Items.Add("Connected");
lbConnect.Items.Add("Sending string: " + str);
Application.DoEvents();
Stream stream = tcpClient.GetStream();
ASCIIEncoding asen= new ASCIIEncoding();
byte[] ba=asen.GetBytes(str);
lbConnect.Items.Add("Transmitting...");
Application.DoEvents();
stream.Write(ba,0,ba.Length);
byte[] bb=new byte[100];
int k = stream.Read(bb,0,100);
string sResponse = string.Empty;
for (int i = 0; i < k; i++) {
sResponse += Convert.ToChar(bb[i]);
}
lbConnect.Items.Add(sResponse);
Application.DoEvents();
tcpClient.Close();
}
catch (Exception e) {
lbConnect.Items.Add("Error: " + e.StackTrace);
Application.DoEvents();
}
}
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();
}
Okay, I've been looking around and have found tutorials on both sending custom objects over TCP and also connecting multiple clients to one server, however I haven't been able to find an example of both so have decided to try it myself however I'm stuck. I so far have written a server that can handle an unlimited number of clients but have failed to implement sending of objects. This is the code I have so far for sending custom objects:
Client code:
Person p = new Person("Tyler", "Durden", 30); // create my serializable object
string serverIp = "127.0.0.1";
TcpClient client = new TcpClient(serverIp, 9050); // have my connection established with a Tcp Server
IFormatter formatter = new BinaryFormatter(); // the formatter that will serialize my object on my stream
NetworkStream strm = client.GetStream(); // the stream
formatter.Serialize(strm, p); // the serialization process
strm.Close();
client.Close();
Server code:
TcpListener server = new TcpListener(9050);
server.Start();
TcpClient client = server.AcceptTcpClient();
NetworkStream strm = client.GetStream();
IFormatter formatter = new BinaryFormatter();
Person p = (Person)formatter.Deserialize(strm); // you have to cast the deserialized object
strm.Close();
client.Close();
server.Stop();
This is the code I currently have for multiple clients:
Server code:
private ArrayList m_aryClients = new ArrayList(); //List of connected clients (Used for threading)
public Program()
{
//Empty constructor
}
static Program()
{
}
#region Main Enty Point
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
//Set log file location
setLogFileLocation("/usr/local/bin/ClipCloud/" + DateTime.Now.ToShortDateString() + ".log");
//Start the application
printAndLog("Starting server");
Program appmain = new Program();
//Get local hostname
IPAddress[] addressList = null;
string hostName = "";
try
{
hostName = Dns.GetHostName();
addressList = Dns.GetHostByName(hostName).AddressList;
}
catch (Exception ex)
{
printAndLog("Failed to get local address (" + ex.Message + ")", 1);
}
//Start listening and set up threads
if ((addressList == null ? false : (int)addressList.Length >= 1))
{
object[] objArray = new object[] { "Listening on : (", hostName, ") ", addressList[0], ",", 399 };
printAndLog(string.Concat(objArray), 0);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(addressList[0], 399));
socket.Listen(10);
socket.BeginAccept(new AsyncCallback(appmain.OnConnectRequest), socket);
//Wait until user types exit
while (!(Console.ReadLine().ToLower() == "exit"))
{}
printAndLog("Shutting down server");
socket.Close();
//Clean up after yourself
GC.Collect();
GC.WaitForPendingFinalizers();
printAndLog("Application successfully shutdown");
}
else
{
printAndLog("Unable to obtain local address" , 2);
}
}
#endregion
#region Server requests
public void NewConnection(Socket sockClient)
{
//new client connected
ClientHandler clientHandler = new ClientHandler(sockClient);
m_aryClients.Add(clientHandler);
printAndLog(string.Concat("Client (",clientHandler.Sock.RemoteEndPoint, ") connected"));
//Send client welcome message
DateTime now = DateTime.Now;
string str = string.Concat("{", now.ToString("G"), "}");
byte[] bytes = Encoding.ASCII.GetBytes(str.ToCharArray());
clientHandler.Sock.Send(bytes, (int)bytes.Length, SocketFlags.None);
clientHandler.SetupRecieveCallback(this);
}
public void OnConnectRequest(IAsyncResult ar)
{
try
{
Socket asyncState = (Socket)ar.AsyncState;
NewConnection(asyncState.EndAccept(ar));
asyncState.BeginAccept(new AsyncCallback(OnConnectRequest), asyncState);
}
catch (Exception ex)
{
printAndLog(ex.Message);
}
}
public void OnRecievedData(IAsyncResult ar)
{
ClientHandler asyncState = (ClientHandler)ar.AsyncState;
byte[] recievedData = asyncState.GetRecievedData(ar);
if ((int)recievedData.Length >= 1)
{
foreach (ClientHandler mAryClient in this.m_aryClients)
{
try
{
//This is where all data is sent out to all users!
mAryClient.Sock.Send(recievedData);
}
catch
{
printAndLog(string.Concat("Failed to send data to client (", asyncState.Sock.RemoteEndPoint, ")"), 2);
mAryClient.Sock.Close();
this.m_aryClients.Remove(asyncState);
return;
}
}
asyncState.SetupRecieveCallback(this);
}
else
{
printAndLog(string.Concat("Client (", asyncState.Sock.RemoteEndPoint, ") disconnected"), 0);
asyncState.Sock.Close();
this.m_aryClients.Remove(asyncState);
}
}
#endregion
}
internal class ClientHandler
{
private Socket m_sock;
private byte[] m_byBuff = new byte[50];
public Socket Sock
{
get
{
return this.m_sock;
}
}
public ClientHandler(Socket sock)
{
this.m_sock = sock;
}
public byte[] GetRecievedData(IAsyncResult ar)
{
int num = 0;
try
{
num = this.m_sock.EndReceive(ar);
}
catch
{
}
byte[] numArray = new byte[num];
Array.Copy(this.m_byBuff, numArray, num);
return numArray;
}
public void SetupRecieveCallback(Program app)
{
try
{
AsyncCallback asyncCallback = new AsyncCallback(app.OnRecievedData);
this.m_sock.BeginReceive(this.m_byBuff, 0, (int)this.m_byBuff.Length, SocketFlags.None, asyncCallback, this);
}
catch (Exception ex)
{
Console.WriteLine("Recieve callback setup failed! {0}", ex.Message);
}
}
}
Can someone please help me connecting the two.