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 ;)
Related
I am using sockets for TCP-IP connection and I would like to establish simple system send-receive from the client side.
Socket sck;
sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint localEndpt = new IPEndPoint(IPAddress.Parse("123.123.123.1"), 12345);
try
{
sck.Connect(localEndpt);
}
catch
{
Console.Write("Unable to Connect");
}
while (true)
{
Console.WriteLine("Enter Text");
string sendtext = Console.ReadLine();
byte[] Data = Encoding.ASCII.GetBytes(sendtext);
sck.Send(Data);
Console.WriteLine("Data Sent!");
byte[] bytesReceived = new byte[sck.ReceiveBufferSize];
int bytes = 0;
String strReceived = "";
int dataAvailable = 0;
while (dataAvailable == 0 || dataAvailable != sck.Available)
{
dataAvailable = sck.Available;
Thread.Sleep(100); // if no new data after 100ms assume transmission finished
}
if (sck.Available > 0)
{
bytes = sck.Receive(bytesReceived, bytesReceived.Length, 0);
strReceived+=Encoding.ASCII.GetString(bytesReceived, 0, bytes);
}
Console.WriteLine("Received from server: " + strReceived);
}
Console.Read();
The problem is that first requests goes throught but the second does not, because socket is not available anymore (socket "Availabe" attribute value is 0). What am I doing wrong? What would be the easiest way to establish multiple send-recieve requests (in order)?
This code works fine for me
private List<Socket> _clients = new List<Socket>();
private Thread _dataReceiveThread;
private bool _isConnected;
private void DataReceive()
{
while (_isConnected)
{
List<Socket> clients = new List<Socket>(_clients);
foreach (Socket client in clients)
{
try
{
if (!client.Connected) continue;
string txt = "";
while (client.Available > 0)
{
byte[] bytes = new byte[client.ReceiveBufferSize];
int byteRec = client.Receive(bytes);
if (byteRec > 0)
txt += Encoding.UTF8.GetString(bytes, 0, byteRec);
}
if (!string.IsNullOrEmpty(txt))
/* TODO: access the text received with "txt" */
}
catch (Exception e)
{
Exception_Handler(e);
}
}
}
}
Just run this code to get started
_isConnected = true;
_dataReceiveThread = new Thread(DataReceive);
_dataReceiveThread.Start();
Update list box in Cross thread:
This code can be placed in the comment section.
myListBox1.Invoke((Action)(() => { myListBox1.Items.Add(txt) }));
Socket. Available does NOT indicate whether the socket is available, but incoming data is available for reading:
https://msdn.microsoft.com/en-us/library/ee425135.aspx
Your program quits because it checks for a reply (incoming data) immediately after sending a message out. Use a Thread.Sleep before checking for data.
Maybe the message has not even been sent, because Socket.Send just places it in the network interface card's output buffer. When the socket finally sends the message, it will upare the connection state. If it got no reply (on a TCP connection), it will tell you that it is disconnected when you query the state. On UDP it will tell you nothing, because UDP is connectionless.
I have a TCP server which writes data back to the client only for certain messages which the clients sends to the server.
It is basically is a command based server for which the server responds with a string only for certain commands otherwise nothing is sent back to the client.
The code given below is an approach which assumes that if any data is sent by the server it shows it as "MESSAGE FROM SERVER" appended with the data which was sent.
class TcpEchoClient
{
static void Main(string[] args)
{
Console.WriteLine("Starting echo client...");
string ipaddress = "127.0.0.1";
TcpClient client = null;
NetworkStream netstream = null;
try
{
client = new TcpClient(ipaddress,1000);
netstream = client.GetStream();
}
catch
{
Console.ReadKey();
Environment.Exit(0);
}
while(true)
{
Console.WriteLine("Message : ");
string t = Console.ReadLine();
string readdata = null;
Console.WriteLine("\n");
if (write(t,netstream))
{
Console.WriteLine("Message sent.");
if (client.Available!=0)
{
readdata = read(netstream);
Console.WriteLine("MESSAGE FROM SERVER : "+readdata);
}
}
else
{
Console.WriteLine("Unable to send message.");
}
}
}
static bool write(string dat, NetworkStream stream)
{
try
{
StreamWriter writer = new StreamWriter(stream) { AutoFlush = true };
try{writer.WriteLine(dat);}
catch (IOException){return false;}
if (SHAHash(dat, "DATA") != SHAHash(read(stream), "DATA"))
return false;
}catch (InvalidOperationException){return false;}
return true;
}
static string read(NetworkStream stream)
{
StreamReader reader = new StreamReader(stream);
string readdata = null;
try
{
readdata = reader.ReadLine();
reader.BaseStream.Flush();
}
catch(IOException)
{
return null;
}
return readdata;
}
}
The function SHAHash is not shown in this post. Its format is SHAHash(message,salt).
The problem faced is that messages sent by the server is not always read by the client. Sometimes the data sent by the server shows up a the client console, and sometimes it does not.
What correction should I make to the above code so that I can read data from the server only when it sends it. That is I require the following code to be executed only when the server sends some data to the client otherwise it should not be executed.
readdata = read(netstream);
Console.WriteLine("MESSAGE FROM SERVER : "+readdata);
Be prudent when using flush or autoflush. Sometimes it executes before send/receive operations... but this usually happens when working with threads.
My first tip that the stream readers/writers are not destructed properly. Try packing them into a using statement.
TCP isnt synchronous so you can't write data and expect the response to be available immediately. When you do the following check
if (client.Available!=0)
there is no guarantee that the server has sent any response yet. You need to keep checking until there is data available or read the data asynchronously
I would use NetworkStream.BeginRead and callbacks to get the server response
class StreamData
{
public NetworkStream netstream;
public byte[] myReadBuffer;
}
class TcpEchoClient
{
static void Main(string[] args)
{
Console.WriteLine("Starting echo client...");
string ipaddress = "127.0.0.1";
TcpClient client = null;
NetworkStream netstream = null;
try
{
client = new TcpClient(ipaddress, 13000);
netstream = client.GetStream();
}
catch
{
Console.ReadKey();
Environment.Exit(0);
}
var streamData = new StreamData
{
netstream = netstream,
myReadBuffer = new byte[1024],
};
netstream.BeginRead(streamData.myReadBuffer, 0, streamData.myReadBuffer.Length,
new AsyncCallback(myReadCallBack),
streamData);
while (true)
{
Console.WriteLine("Message : ");
string t = Console.ReadLine();
Console.WriteLine("\n");
if (write(t, netstream))
{
Console.WriteLine("Message sent.");
}
else
{
Console.WriteLine("Unable to send message.");
}
}
}
static void myReadCallBack(IAsyncResult ar)
{
var streamData = (StreamData)ar.AsyncState;
int bytesRead = streamData.netstream.EndRead(ar);
var readdata = Encoding.ASCII.GetString(streamData.myReadBuffer, 0, bytesRead);
//Be aware that this might not be the complete message depending on the size of the message and the buffer size
Console.WriteLine("You received the following message : " + readdata);
//Start waiting for more data
streamData.netstream.BeginRead(streamData.myReadBuffer, 0, streamData.myReadBuffer.Length,
new AsyncCallback(myReadCallBack),
streamData);
}
static bool write(string dat, NetworkStream stream)
{
try
{
StreamWriter writer = new StreamWriter(stream) { AutoFlush = true };
try { writer.WriteLine(dat); }
catch (IOException) { return false; }
//if (SHAHash(dat, "DATA") != SHAHash(read(stream), "DATA"))
// return false;
}
catch (InvalidOperationException) { return false; }
return true;
}
}
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 developing a networking application.
The server program gives questions, then clients enters their answers.
Actually, both server program and client program were console program.
But, when I changed client program to Form program, It doesn't display. (ONLY WHEN I TURN ON SERVER PROGRAM!)
It works when i don't start server program.
Here's my server program code,
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace Server
{
public class TaskInfo
{
public Socket client;
public int thread_num;
public int q_num;
public ManualResetEvent doneEvent;
public TaskInfo(Socket c, int n, int q, ManualResetEvent d)
{
client = c;
thread_num = n;
q_num = q;
doneEvent = d;
}
}
public class ServerTCP
{
static int num_client = 2;
static bool[] check_co_client = new bool[num_client];
static int num_co_client = 0;
static void ClientHandler(Object task_info)
{
TaskInfo ti = (TaskInfo)task_info;
// Casting of object
Socket client = (Socket)ti.client;
IPEndPoint endpoint = (IPEndPoint)client.RemoteEndPoint;
//Console.WriteLine("{0} connected at port {1}", endpoint.Address, endpoint.Port);
int index = ti.q_num;
byte[] buffer = new byte[256];
int byteRecv = 0;
string message = "";
string[] questions = new string[5];
questions[0] = "0. What is 5+6?";
questions[1] = "1. What is 1+3?";
questions[2] = "2. What is 5+3?";
questions[3] = "3. What is 1+1?";
questions[4] = "4. What is 9-5?";
string[] answers = new string[5];
answers[0] = "11";
answers[1] = "4";
answers[2] = "8";
answers[3] = "2";
answers[4] = "4";
try
{
// Send message to client
buffer = Encoding.ASCII.GetBytes(questions[index]);
client.Send(buffer, buffer.Length, SocketFlags.None);
// Receive data from client
byteRecv = client.Receive(buffer);
message = Encoding.ASCII.GetString(buffer, 0, byteRecv);
if (message == answers[ti.q_num])
{
check_co_client[ti.thread_num] = true;
}
else
{
check_co_client[ti.thread_num] = false;
}
ti.doneEvent.Set();
}
catch (SocketException se)
{
Console.WriteLine("{0}: {1} [{2}:{3}]", se.ErrorCode, se.Message, endpoint.Address, endpoint.Port);
}
finally
{
// Close socket
//client.Close();
}
}
public static void Main()
{
TcpListener listener = null;
try
{
// Create new instance and start listening
listener = new TcpListener(IPAddress.Any, 8080);
listener.Start();
Console.WriteLine("<Waiting for clients connection>");
// Accept the client connection
Socket[] client = new Socket[num_client];
int count = 0;
while (count < num_client)
{
client[count] = listener.AcceptSocket();
count++;
}
ManualResetEvent[] doneEvents = new ManualResetEvent[num_client];
// Start threads
Thread[] t = new Thread[num_client];
for (int q_num = 0; q_num < 5; q_num++)
{
for (int i = 0; i < num_client; i++)
{
doneEvents[i] = new ManualResetEvent(false);
TaskInfo ti = new TaskInfo(client[i], i, q_num, doneEvents[i]);
t[i] = new Thread(ClientHandler);
t[i].Start(ti);
}
WaitHandle.WaitAll(doneEvents);
Thread.Sleep(2000);
// count clients who enter correct answer
for (int index = 0; index < num_client; index++)
{
if (check_co_client[index])
{
num_co_client++;
}
}
Console.WriteLine("number of correct answers: {0}", num_co_client);
num_co_client = 0;
}
}
catch (SocketException se)
{
Console.WriteLine("Error Code: {0}", se.ErrorCode);
Console.WriteLine("Message: {0}", se.Message);
}
finally
{
listener.Stop();
}
Console.ReadLine(); // Pause for IDE
}
}
}
and here's my client program code,
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace Client_Form
{
public partial class Client_Form : Form
{
TcpClient client = null;
NetworkStream stream = null;
int count = 0;
public Client_Form()
{
InitializeComponent();
Start_Program();
}
private void Start_Program()
{
try
{
// Connect to server
client = new TcpClient("127.0.0.1", 8080);
//Console.WriteLine("<Connected to server>");
textBox.Text = "<Connected to server>";
stream = client.GetStream();
byte[] buffer = new byte[256];
int byteRecv = 0;
string message = "";
int q_count = 5;
while (count < q_count)
{
while ((byteRecv = stream.Read(buffer, 0, buffer.Length)) == 0)
{
textBox.Text = "Waiting for other client";
Thread.Sleep(3000);
}
// Get data from server
//byteRecv = stream.Read(buffer, 0, buffer.Length);
message = Encoding.ASCII.GetString(buffer, 0, byteRecv);
Co_Game_Question.Text = message;
}
// Close stream and connection
stream.Close();
client.Close();
//Console.WriteLine("<Connection closed>");
textBox.Text = "<Connection closed>";
}
catch (SocketException se)
{
//Console.WriteLine("Error: {0}", se.SocketErrorCode);
//Console.WriteLine("Error Code: {0}", se.ErrorCode);
//Console.WriteLine("Message: {0}", se.Message);
textBox.Text = "Error Message: " + se.Message;
}
}
private void Btn_Enter_Click(object sender, EventArgs e)
{
// Send message to server
//Console.Write("Answer {0}> ", count);
//textBox.Text = "Answer " + count + "> ";
byte[] data = Encoding.ASCII.GetBytes(User_answer_box.Text);
stream.Write(data, 0, data.Length);
count++;
}
}
}
How can I solve this problem??
Thanks for reading my question!
Since you are already using NetworkStream, fixing the client code is easy. Just switch over to the async/await idiom:
namespace Client_Form
{
public partial class Client_Form : Form
{
TcpClient client = null;
NetworkStream stream = null;
int count = 0;
public Client_Form()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
// Handling the network operations after the form loads ensures
// that the asynchronous operations will come back to the main
// thread as desired.
// Ignore returned Task
var _ = Start_Program();
}
private async void Start_Program()
{
try
{
// Connect to server
client = await Task.Run(() => new TcpClient("127.0.0.1", 8080));
textBox.Text = "<Connected to server>";
stream = client.GetStream();
byte[] buffer = new byte[256];
int q_count = 5;
while (count < q_count)
{
textBox.Text = "Waiting for other client";
// Get data from server
int byteRecv = await stream.ReadAsync(buffer, 0, buffer.Length);
string message = Encoding.ASCII.GetString(buffer, 0, byteRecv);
Co_Game_Question.Text = message;
}
// Close stream and connection
stream.Close();
client.Close();
textBox.Text = "<Connection closed>";
}
catch (SocketException se)
{
textBox.Text = "Error Message: " + se.Message;
}
}
}
}
Now, that said, you had and still have some other bugs. First, your original code had a loop that read from the stream until the return value was 0. All that's going to do is consume the data in the stream without processing any of it. Very bad. I removed that bug completely in the example above.
Second, you are not checking the return value of the read. TCP guarantees only one thing: that if you receive any data, the bytes that you receive are in the same order in which they were sent. In particular, there are no guarantees about how many bytes you'll receive in any given call to Read(). If the remote endpoint sends 100 bytes, you could receive all 100 bytes all at once, or you could receive 1 byte at a time in 100 calls to Read().
(Well, actually that's highly unlikely to ever happen...but it's not prohibited by the TCP contract, and in any case if you assume it's true you'll write correct code).
That's really a whole other question. The above will get your Forms program back to working, in that you'll actually be able to see the Form and interact with it. And the network code might even seem to work for awhile. But eventually you'll get a partial message, or multiple messages combined into one, or some other variation on that theme.
When that happens, IMHO one of the easiest ways to fix that in a scenario like yours is to switch to a line-based data scheme. I.e. wrap the NetworkStream object in StreamReader and StreamWriter objects, and use the ReadLineAsync() method to receive data instead of the NetworkStream.Read() method. Regardless, feel free to post another question when you come to that bridge. :)
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.)