I have a code snippet which is reading data from ip address and port.Now as per my need i have to save this data into text file but i dont know how to do it ..
Here is my code ...
class Listener
{
private TcpListener tcpListener;
private Thread listenThread;
// Set the TcpListener on port 8081.
Int32 port = 8081;
IPAddress localAddr = IPAddress.Parse("192.168.1.3");
Byte[] bytes = new Byte[256];
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void HandleClientComm(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
{
//a socket error has occured
// System.Windows.MessageBox.Show("socket");
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
// System.Windows.MessageBox.Show("disc");
break;
}
//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
//Here i need to save the data into text file ...
}
tcpClient.Close();
}
}
And my text file address is ...
D:\ipdata.txt
Please help me ..
Thanks in advance..
You can create a FileStream using File.Open() or File.OpenWrite():
using (Stream output = File.OpenWrite(#"D:\ipdata.txt"))
{
// the while loop goes in here
}
You are hinting the use of ASCIIEncoding. Usually if you receive ASCII you don't need to decode the data - you could simply write the data to the file directly:
if (bytesRead == 0)
{
break;
}
else
{
output.Write(message, 0, bytesRead);
}
If some kind of decoding needs to take place, you may need to buffer the incoming data and either write the entire thing after the socket has disconnected, or write in batches. For example if you expect UTF-16, there is no guarantee that you receive an even number of bytes on each Read().
PS none of the code is tested, it's supposed to be just an example.
Related
I am trying to send a message from a Socket client I created in C# on an Android device to a TCPListener server on my PC. The message is sent and I can see it printed on the output of the terminal as I programmed it to but now the server prints the first letter of the message only like when I send David, it only prints D. I need help to revise my code and make it print the entire message sent from the Android client. The code for the server program is below
static void Main(string[] args)
{
TcpListener server = null;
try
{
//decide where the aplication will listen for connections
int port = 13000;
IPAddress localAddress = IPAddress.Parse("192.168.49.147");
server = new TcpListener(localAddress, port);
//start listening for client requests
server.Start();
//initialize buffer for reading data received from a client
byte[] bytes = new byte[256];
string? data;
data = null;
//enter into the listening loop
while (true)
{
Console.WriteLine("Listening for connections");
//perform a blocking call to accept requests
//You could also use a server.Accept() to accept an incoming connection
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected");
data = null;
//get a stream object for reading and writing
NetworkStream stream = client.GetStream();
int i;
//loop to receive all the data
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
//translate the byte received into ASCII encoded data
//something is wrong here as it prints the first character of the string
data = System.Text.Encoding.ASCII.GetString(bytes, 0, 1);
Console.WriteLine("Received: {0}", data);
//process the data sent ny the client
data.ToUpper();
byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
// Send back a response.
stream.Write(msg, 0, msg.Length);
Console.WriteLine("Sent: {0}", data);
}
//shut down and end connection
client.Close();
}
}catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
//stop listening for new connections
server.Stop();
}
}
I am trying to write a server that will listen on a port, accept an incoming client connection and then put that client connection in a stack to wait for a future message to arrive. Ideally when a message arrives, I'd like to fire an event that then allows the server to perform an action.
I've written almost all of that...I am using AcceptTCPClient() to actually pick up a new client connection which is fine. I then create a thread, pass the socket to a class that holds the client state and some other data. However the only way I can think to block and wait for a future incoming connection on that thread is to call something like NetworkStream.Read() which then blocks until bytes arrive.
So here is the fundamental problem - I am using Protobuff-net which allows me to deserialise a network stream rather than an individual byte array. So by reading the first couple of bytes, I've got to reset the read, pass the networkstream to the protobuff deserialize method and then continue.
All I really want is a method that blocks until some bytes are detected but doesn't require me to actually read the bytes until I'm ready.
Anyone have any ideas how I could achieve this?
Update
As the comments below suggested, this is not something that seems to be supported by .Net therefore the simplest solution seems to be to use Tsukasa example below which uses async read/write.
I've written it to consume all the bytes on the wire and then pass those bytes to the protobuff Deserialize method.
Not what I wanted but it works fine. Thanks all for the assitance.
private byte[] buffer = new byte[256];
private Socket socket;
private NetworkStream networkStream;
private AsyncCallback callbackRead;
private AsyncCallback callbackWrite;
public Socket Socket
{
get { return socket; }
}
public ClientProxy(Socket clientSocket)
{
socket = clientSocket;
networkStream = new NetworkStream(clientSocket);
callbackRead = new AsyncCallback(OnReadComplete);
callbackWrite = new AsyncCallback(OnWriteComplete);
}
public void ReadAsync()
{
networkStream.BeginRead(buffer, 0, buffer.Length, callbackRead, null);
}
private void OnReadComplete(IAsyncResult ar)
{
int bytesRead = networkStream.EndRead(ar);
if (bytesRead > 0)
{
MemoryStream stream = new MemoryStream(buffer);
Message data;
data = Serializer.DeserializeWithLengthPrefix<Message>(stream, PrefixStyle.Fixed32);
if (data.Type == Chat.Type.User && data.Action == Chat.Action.Add)
{
Communication.RegisterClient(data.From, socket.Handle.ToString());
}
Communication.readMessage(data);
ReadAsync();
}
else
{
networkStream.Close();
socket.Close();
networkStream = null;
socket = null;
}
}
You can poll the DataAvailable property but it's unreliable and inefficient.
A better way is to prefix the protobuf stream with a length prefix. It also allows to do a read without reading the protobuf message. By using a prefix you can invoke a asynchronous read which will return as soon as there is something available (just configure the Read to read only 4 bytes if you are using a length header).
If you don't want to take care of the network operations yourself you can use my apache licensed library. Here is a sample using protobuf-net: http://blog.gauffin.org/2014/06/easy-and-perfomant-clientserver-communication-with-protobuf-net-griffin-framework/
BeginRead() which would allow you to have an event called when data is ready, that way your process can be in a blocked state where the OS will only awake it when the resource is ready
class Client
{
private byte[] buffer = new byte[256];
private Socket socket;
private NetworkStream networkStream;
private AsyncCallback callbackRead;
private AsyncCallback callbackWrite;
public Client(Socket clientSocket)
{
socket = clientSocket;
networkStream = new NetworkStream(clientSocket);
callbackRead = new AsyncCallback(OnReadComplete);
callbackWrite = new AsyncCallback(OnWriteComplete);
}
public void StartRead()
{
networkStream.BeginRead(buffer, 0, buffer.Length, callbackRead, null);
}
private void OnReadComplete(IAsyncResult ar)
{
int bytesRead = networkStream.EndRead(ar);
if (bytesRead > 0)
{
string s = System.Text.Encoding.ASCII.GetString(buffer, 0, bytesRead);
//do something with complete data here
networkStream.BeginWrite(buffer, 0, bytesRead, callbackWrite, null);
}
else
{
networkStream.Close();
socket.Close();
networkStream = null;
socket = null;
}
}
private void OnWriteComplete(IAsyncResult ar)
{
networkStream.EndWrite(ar);
networkStream.BeginRead(buffer, 0, buffer.Length, callbackRead, null);
}
}
Usage
bool running = true;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
TcpListener tcpListener = new TcpListener(localAddr, 3000);
tcpListener.Start();
while (running)
{
while (!tcpListener.Pending())
{
Thread.Sleep(10);
}
Socket socket = tcpListener.AcceptSocket();
Client client = new Client(socket);
client.StartRead();
}
I have an issue with a TCP Listener.
The scenario is the following:
- I am receiving TCP packets (8192 Bytes each) and I would like to dump the data received from NetworkStream into a file (using FileStream);
- What I saw is that all the TCP packets arrived to the TCP listener but only the first 8192 Bytes are dumped into the file.
I believe that the NetStream is faster than the IO operation to the file.
My code is:
try
{
// Set TcpListener on port 8
Int32 portN = 8;
TcpListener server = new TcpListener(IPAddress.Any, portN);
// Start listening for client requests
server.Start();
Console.Write("Waiting for connection... ");
// Define File Name
string RcvFileName = #"c:\ethernet\out_file.raw";
// Buffer for reading data
int NrBytesRec;
Byte[] RecData = new Byte[8192];
// enter into listening loop
while (true)
{
// Perform a blocking call to accept requests.
// You can also user server.AcceptSocket() here.
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
// Get a stream object for reading and writing
NetworkStream netstream = client.GetStream();
// Append data into file
FileStream fs_wr = new FileStream(RcvFileName, FileMode.Append, FileAccess.Write);
// Dump data
while ((NrBytesRec = netstream.Read(RecData, 0, RecData.Length)) > 0)
{
fs_wr.Write(RecData, 0, NrBytesRec);
Console.WriteLine("Received: {0}", NrBytesRec);
}
netstream.Close();
fs_wr.Close();
//client.Close();
}
I have a code in c# which reads the data from tcp ipaddress and port number but my problem is this that i dont have any testing plateform with ipaddress and port number to test the application.My concern is this that is there any way by which i can test my code in local environmnet..
Here is my code..
public class Listener
{
private TcpListener tcpListener;
private Thread listenThread;
// Set the TcpListener on port 8081.
Int32 port = 8081;
IPAddress localAddr = IPAddress.Parse("192.168.1.3");
Byte[] bytes = new Byte[256];
public void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
public void HandleClientComm(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
{
//a socket error has occured
// System.Windows.MessageBox.Show("socket");
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
// System.Windows.MessageBox.Show("disc");
break;
}
//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
String textdata = encoder.GetString(message, 0, bytesRead);
System.IO.File.AppendAllText(#"D:\ipdata.txt", textdata);
}
tcpClient.Close();
}
}
Please help me to solve this ..
Thanks in advance..
To test the TCP listening application, you obviously need to write TCP transferring one. You can write it and:
Run them simultaneously
OR
Run listener on your OS and transmitter in virtual machine. I made so and has written a post on my blog on Russian (sources are also available for download).
I think you can configure the listener to 127.0.0.1 and test logic via localhost connetcion if you have transmitting part of system
Use RESTClient chrome/firefox AddOn (http://restclient.net/) to send data to IP and Port in Intranet environment, I use this
I have a GUI with 2 buttons and a text box. Button1 starts a server and has it listen for clients. Button 2 sends a connection request to the server and starts to listen for anything the server will send to the client (responses). Although w/ my current code when the Server sends the reply and I try to write it to a text box the whole system hangs.
Code as seen below:
Server Class:
class Server
{
private TcpListener tcpListener;
private Thread listenThread;
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void HandleClientComm(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
{
//a socket error has occured
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Client!");
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
tcpClient.Close();
}
public Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
}
GUI class:
private void buttonServerStart_Click(object sender, EventArgs e)
{
Server Myserver = new Server();
}
//Greet the Server and listen for response...
private void EthStartB_Click(object sender, EventArgs e)
{
TcpClient client = new TcpClient();
byte[] message = new byte[4096];
int bytesRead;
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);
client.Connect(serverEndPoint);
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Server!");
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
//start listening
this.ClientListener.Start();
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
//message has successfully been received
tb_recieved.Clear();
tb_recieved.Text=encoder.GetString(message,0,bytesRead);
}
}
TcpListener ClientListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 3000);
private void EthEndB_Click(object sender, EventArgs e)
{
Form3 frmT = new Form3();
frmT.Show();
}
}
The issue is when private void EthStartB_Click(object sender, EventArgs e) calls the code line of tb_recieved.Text=encoder.GetString(message,0,bytesRead);
The program hangs because you have a while(true) loop in EthStartB_Click which runs on UI thread. clientStream.Read call will block UI thread.
Move the receive logic on a new thread and set the textbox content using Control.Invoke or Dipatcher.Invoke depending on whether you are on WinForms or WPF - and do that only if you do have some content in the message to be written to textbox.
There also another issue, since you have the tcpClient.Close() outside the while loop on the server, neither client nor server will disconnect. Both will block on their respective stream.Read calls.
Since you are running both client and server on same machine, that TcpListener ClientListener is not required and will not play well with the server already listening on the same port.