Reputation: 8054
I have two basic console apps that communicate "over the network" even though all of the communication takes place on my local machine.
Client code:
public static void Main()
{
while (true)
{
try
{
TcpClient client = new TcpClient();
client.Connect("127.0.0.1", 500);
Console.WriteLine("Connected.");
byte[] data = ASCIIEncoding.ASCII.GetBytes(new FeederRequest("test", TableType.Event).GetXmlRequest().ToString());
Console.WriteLine("Sending data.....");
using (var stream = client.GetStream())
{
stream.Write(data, 0, data.Length);
stream.Flush();
Console.WriteLine("Data sent.");
}
client.Close();
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.StackTrace);
Console.ReadLine();
}
}
}
Server code:
public static void Main()
{
try
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
Console.WriteLine("Starting TCP listener...");
TcpListener listener = new TcpListener(ipAddress, 500);
listener.Start();
Console.WriteLine("Server is listening on " + listener.LocalEndpoint);
while (true)
{
Socket client = listener.AcceptSocket();
Console.WriteLine("\nConnection accepted.");
var childSocketThread = new Thread(() =>
{
Console.WriteLine("Reading data...\n");
byte[] data = new byte[100];
int size = client.Receive(data);
Console.WriteLine("Recieved data: ");
for (int i = 0; i < size; i++)
Console.Write(Convert.ToChar(data[i]));
//respond to client
Console.WriteLine("\n");
client.Close();
Console.WriteLine("Waiting for a connection...");
});
childSocketThread.Start();
}
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.StackTrace);
Console.ReadLine();
}
}
How can I alter both of these applications so that when the Server has received the data, it responds to the Client with some kind of confirmation?
Thanks in advance!
Upvotes: 1
Views: 4272
Reputation: 933
Here a short example how I would do it:
Server:
class Server
{
static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Any, 1500);
listener.Start();
TcpClient client = listener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
// Create BinaryWriter for writing to stream
BinaryWriter binaryWriter = new BinaryWriter(stream);
// Creating BinaryReader for reading the stream
BinaryReader binaryReader = new BinaryReader(stream);
while (true)
{
// Read incoming information
byte[] data = new byte[16];
int receivedDataLength = binaryReader.Read(data, 0, data.Length);
string stringData = Encoding.ASCII.GetString(data, 0, receivedDataLength);
// Write incoming information to console
Console.WriteLine("Client: " + stringData);
// Respond to client
byte[] respondData = Encoding.ASCII.GetBytes("respond");
Array.Resize(ref respondData, 16); // Resizing to 16 byte, because in this example all messages have 16 byte to make it easier to understand.
binaryWriter.Write(respondData, 0, 16);
}
}
}
Client:
class Client
{
private static void Main(string[] args)
{
Console.WriteLine("Press any key to start Client");
while (! Console.KeyAvailable)
{
}
TcpClient client = new TcpClient();
client.Connect("127.0.0.1", 1500);
NetworkStream networkStream = client.GetStream();
// Create BinaryWriter for writing to stream
BinaryWriter binaryWriter = new BinaryWriter(networkStream);
// Creating BinaryReader for reading the stream
BinaryReader binaryReader = new BinaryReader(networkStream);
// Writing "test" to stream
byte[] writeData = Encoding.ASCII.GetBytes("test");
Array.Resize(ref writeData, 16); // Resizing to 16 byte, because in this example all messages have 16 byte to make it easier to understand.
binaryWriter.Write(writeData, 0, 16);
// Reading response and writing it to console
byte[] responeBytes = new byte[16];
binaryReader.Read(responeBytes, 0, 16);
string response = Encoding.ASCII.GetString(responeBytes);
Console.WriteLine("Server: " + response);
while (true)
{
}
}
}
I hope this helps! ;)
Upvotes: 7
Reputation: 4777
Here's an example of what (I think) you want to do:
static void Main(string[] args) {
var server = new Task(Server);
server.Start();
System.Threading.Thread.Sleep(10); // give server thread a chance to setup
try {
TcpClient client = new TcpClient();
client.Connect("127.0.0.1", 1500);
Console.WriteLine("Connected.");
var data = new byte[100];
var hello = ASCIIEncoding.ASCII.GetBytes("Hello");
Console.WriteLine("Sending data.....");
using (var stream = client.GetStream()) {
stream.Write(hello, 0, hello.Length);
stream.Flush();
Console.WriteLine("Data sent.");
// You could then read data from server here:
var returned = stream.Read(data, 0, data.Length);
var rec = new String(ASCIIEncoding.ASCII.GetChars(data, 0, data.Length));
rec = rec.TrimEnd('\0');
if (rec == "How are you?") {
var fine = ASCIIEncoding.ASCII.GetBytes("fine and you?");
stream.Write(fine, 0, fine.Length);
}
}
client.Close();
Console.ReadLine();
}
catch (Exception e) {
Console.WriteLine("Error: " + e.StackTrace);
Console.ReadLine();
}
}
public static void Server() {
try {
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
Console.WriteLine("*Starting TCP listener...");
TcpListener listener = new TcpListener(ipAddress, 1500); // generally use ports > 1024
listener.Start();
Console.WriteLine("*Server is listening on " + listener.LocalEndpoint);
Console.WriteLine("*Waiting for a connection...");
while (true) {
Socket client = listener.AcceptSocket();
while (client.Connected) {
Console.WriteLine("*Connection accepted.");
Console.WriteLine("*Reading data...");
byte[] data = new byte[100];
int size = client.Receive(data);
Console.WriteLine("*Recieved data: ");
var rec = new String(ASCIIEncoding.ASCII.GetChars(data, 0, size));
rec = rec.TrimEnd('\0');
Console.WriteLine(rec);
if (client.Connected == false) {
client.Close();
break;
}
// you would write something back to the client here
if (rec == "Hello") {
client.Send(ASCIIEncoding.ASCII.GetBytes("How are you?"));
}
if (rec == "fine and you?") {
client.Disconnect(false);
}
}
}
listener.Stop();
}
catch (Exception e) {
Console.WriteLine("Error: " + e.StackTrace);
Console.ReadLine();
}
}
}
Keep in mind that data sent via sockets can arrive fragmented (in different packets). This doesn't usually happen with the packets are small.
Upvotes: 0
Reputation: 1108
You can perform both Read and Write on the same stream. After you send all the data over, just call stream.Read as in
using (var stream = client.GetStream())
{
stream.Write(data, 0, data.Length);
stream.Flush();
Console.WriteLine("Data sent.");
stream.Read(....); //added sync read here
}
MSDN documentation on TcpClient has an example as well http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.aspx
If you want feed back such as reporting # of bytes received so far, you'll have to use async methods.
Upvotes: 0