My goal is to create a TcpClient that stays connected, allowing messages to be sent to the server, as well as having a timed monitor that sends a special message to the server during a certain idle frequency. Haven't made it too far before getting stumped.
With the current code, the first message sent using a console tester app receives fine, but upon sending another an exception is thrown with the message "The operation is not allowed on non-connected sockets."
I have tried removing the stream.Dispose() line and it will hang on stream.Read(...) during the second attempt. I have also tried making NetworkStream stream a member of the class and set it to client.GetStream() in the constructor and it will hang on stream.Read(...) during the second attempt.
public class TcpClientTest
{
private TcpClient client = new TcpClient();
private string hostName;
private int port;
public TcpClientTest(string hostName, int port)
{
this.hostName = hostName;
this.port = port;
client.Connect(hostName, port);
}
public byte[] SendMessage(string name, string message)
{
if (client == null) throw new Exception("Client connection has not been established");
Person person = new Person();
person.Name = name; person.Message = message;
byte[] messageBytes = (System.Text.Encoding.Unicode.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(person)));
const int bytesize = 1024 * 1024;
try
{
NetworkStream stream = client.GetStream();
if (stream != null)
{
stream.Write(messageBytes, 0, messageBytes.Length); // Write the bytes
messageBytes = new byte[bytesize]; // Clear the message
// Receive the stream of bytes
stream.Read(messageBytes, 0, messageBytes.Length);
}
// Clean up
stream.Flush();
stream.Dispose();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return messageBytes; // Return response
}
}
// In console tester app
static void Main(string[] args)
{
TcpClientTest client = new TcpClientTest("127.0.0.1", 1234);
string exit = "2";
do
{
if (exit == "1") client.SendMessage("TEST", "TEST");
Console.WriteLine("1 Send Message 2 Exit");
exit = Console.ReadLine();
} while (exit != "2");
}
I'm making a server - client program using TcpClient and server.
To send from the server I use:
static void send(string data)
{
sw.WriteLine(data + Environment.NewLine);
}
And when the client connects I'm sending some text:
client = listener.AcceptTcpClient();
sr = new StreamReader(client.GetStream());
sw = new StreamWriter(client.GetStream());
string line;
try
{
send("Hello world");
} //More code
And to read from client:
string data;
data = sr.ReadLine();
if(data != string.Empty || data != null)
{
MessageBox.Show(data);
}
I tried putting inside while(true) and it froze, I tried putting inside a timer tick loop and it froze...
How do I fix this?
P.S: The client and the server are 2 different projects.
I believe you need something like this:
try
{
listen = new TcpListener(myAddress, port);
listen.Start();
Byte[] bytes;
while (true)
{
TcpClient client = listen.AcceptTcpClient();
NetworkStream ns = client.GetStream();
if(client.ReceiveBufferSize > 0){
bytes = new byte[client.ReceiveBufferSize];
ns.Read(bytes, 0, client.ReceiveBufferSize);
string msg = Encoding.ASCII.GetString(bytes); //the message incoming
MessageBox.Show(msg);
}
}
}
catch(Exception e)
{
//e
}
Then have this code as a background thread:
Thread thread = new Thread(the functions name);
thread.IsBackground = true;
thread.Start();
I hope I understand what you need.
Try this one, grandpa's way.
int i = 0;
while (stream.DataAvailable == true)
{
bytes[i] = ((byte)stream.ReadByte());
i++;
}
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
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();
}
This is a program to search for strings from a file. The string required by the client is given from the client side, in my case, using telnet. The program I have written is a server side one. It accepts multiple clients.
But, the problems I am unable rectify are-
It doesn't check for strings from the file.
As soon as the client gets connected, the client cannot type in the strings they want to search in that particular file.
It doesn't send the reply back (i.e. If the string is present in the file or not) to the client. Its only shown on the server side.
How do I proceed further? Could someone tell me where am I going wrong? Could someone please help me out with the code?
This is my try at the program..
class Program
{
static void Main(string[] args)
{
IPAddress ipad = IPAddress.Parse("192.168.0.181");
TcpListener serversocket = new TcpListener(ipad, 8888);
TcpClient clientsocket = default(TcpClient);
Byte[] bytes = new Byte[256];
serversocket.Start();
Console.WriteLine(">> Server Started");
while(true)
{
clientsocket = serversocket.AcceptTcpClient();
Console.WriteLine("Accepted Connection From Client");
LineMatcher lm = new LineMatcher(clientsocket);
Thread thread = new Thread(new ThreadStart(lm.Run));
thread.Start();
Console.WriteLine("Client connected");
}
Console.WriteLine(" >> exit");
Console.ReadLine();
clientsocket.Close();
serversocket.Stop();
}
}
public class LineMatcher //I've jumbled it up here. Don't know what exactly to do..
{
public string fileName = "c:/myfile2.txt";
private TcpClient _client;
public LineMatcher(TcpClient client)
{
_client = client;
}
public void Run()
{
try
{
StreamReader sr = new StreamReader("c:/myfile2.txt");
using (var reader = new StreamReader(_client.GetStream()))
{
string line ="";
int lineNumber = 0;
while (null != (line = sr.ReadLine()))
{
lineNumber += 1;
byte[] data = new byte[1024];
NetworkStream stream = _client.GetStream();
//if (line.Equals(line))
for (int ct = stream.Read(data,0, data.Length-1); 0 < ct; ct = stream.Read(data,0,data.Length-1))
line += Encoding.ASCII.GetString(data, 0, ct);
line = line.Trim();
{
lineNumber.ToString();
data = Encoding.ASCII.GetBytes(line);
_client.Client.Send(data, data.Length, SocketFlags.None);
Console.WriteLine("Line {0} matches {1}", lineNumber, line);
}
}
}
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.ToString());
}
Console.WriteLine("Closing client");
_client.Close();
}
}
I think you got some pieces in your Run-method swapped - here is a version that should do the job:
public void Run()
{
byte[] data;
try
{
using (var r = new StreamReader("c:/myfile2.txt"))
{
string line ="";
int lineNumber = 0;
while (null != (line = r.ReadLine()))
{
data = Encoding.ASCII.GetBytes(line + "\n");
_client.Client.Send(data, data.Length, SocketFlags.None);
}
}
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.ToString());
}
Console.WriteLine("Closing client");
_client.Close();
}
Please note that I'm not 100% sure what you are trying to do (I think you want your textfile send line-by-line to your Terminal) - so you might have to change some bits here and there.
Don't know where the Stream-messes in your code came from but I guess you tried various tutorials/snippets and forgot to clean up ;)
i'm trying to write simple tcp\ip client-server.
here is server code:
internal class Program
{
private const int _localPort = 7777;
private static void Main(string[] args)
{
TcpListener Listener;
Socket ClientSock;
string data;
byte[] cldata = new byte[1024];
Listener = new TcpListener(_localPort);
Listener.Start();
Console.WriteLine("Waiting connections [" + Convert.ToString(_localPort) + "]...");
try
{
ClientSock = Listener.AcceptSocket();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return;
}
int i = 0;
if (ClientSock.Connected)
{
while (true)
{
try
{
i = ClientSock.Receive(cldata);
}
catch
{
}
try
{
if (i > 0)
{
data = Encoding.ASCII.GetString(cldata).Trim();
ClientSock.Send(cldata);
}
}
catch
{
ClientSock.Close();
Listener.Stop();
Console.WriteLine(
"Server closing. Reason: client offline. Type EXIT to quit the application.");
}
}
}
}
}
And here is client code:
void Main()
{
string data; // Юзерская дата
byte[] remdata ={ };
TcpClient Client = new TcpClient();
string ip = "127.0.0.1";
int port = 7777;
Console.WriteLine("\r\nConnecting to server...");
try
{
Client.Connect(ip, port);
}
catch
{
Console.WriteLine("Cannot connect to remote host!");
return;
}
Console.Write("done\r\nTo end, type 'END'");
Socket Sock = Client.Client;
while (true)
{
Console.Write("\r\n>");
data = Console.ReadLine();
if (data == "END")
break;
Sock.Send(Encoding.ASCII.GetBytes(data));
Sock.Receive(remdata);
Console.Write("\r\n<" + Encoding.ASCII.GetString(remdata));
}
Sock.Close();
Client.Close();
}
When i'm sending to my server i cannt receive data back answer. Sock.Receive(remdata) returns nothing! Why?
You're trying to receive to an empty buffer. You should allocate the buffer with a sensible size, and then take note of the amount of data received:
byte[] buffer = new byte[1024];
...
int bytesReceived = socket.Receive(buffer);
string text = Encoding.ASCII.GetString(buffer, 0, bytesReceived);
(It's somewhat unconventional to use PascalCase for local variables, by the way. I'd also urge you not to just catch Exception blindly, and not to swallow exceptions without logging them.)