I am trying to send a message between 2 computers. I have been able to establish connection but for some weird reason i have been unable to acquire stream.
Server Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace chat_server
{
class Program
{
static void Main(string[] args)
{
TcpListener server = new TcpListener(IPAddress.Any, 9999);
server.Start();
Console.WriteLine("Waiting for client connections");
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Client request accepted");
NetworkStream stream = client.GetStream();
StreamReader reader = new StreamReader(stream);
StreamWriter writer = new StreamWriter(stream);
Console.WriteLine("The message is " + reader.ReadToEnd());
}
}
}
Client Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace chat_client
{
class Program
{
static void Main(string[] args)
{
TcpClient client = new TcpClient("localhost", 9999);
NetworkStream stream = client.GetStream();
StreamReader reader = new StreamReader(stream);
StreamWriter writer = new StreamWriter(stream);
writer.Write("Hello world");
Console.WriteLine("Message Sent");
Console.ReadKey();
}
}
}
My server code confirms client connection by printing client request accepted. However for some reason i am unable to acquire data from stream. Quick Help would be really appreciated.
Thank you
You need to flush the stream in order to actually send the data.
Try:
writer.Write("Hello world");
writer.Flush();
Take a look at the MSDN docs for more information:
Synchronous socket server: http://msdn.microsoft.com/en-us/library/6y0e13d3.aspx
Asynchronous socket server: http://msdn.microsoft.com/en-us/library/5w7b7x5f.aspx
Here's a site that explains in more detail the ins and outs of sockets: http://nitoprograms.blogspot.co.uk/2009/04/tcpip-net-sockets-faq.html
In server side,
add static TcpListener server; at the top
Then `server.Start();
Socket soc = listener.AcceptSocket();
Console.WriteLine("Connection successful");
Stream s = new NetworkStream(soc);
StreamReader reader = new StreamReader(s);
StreamWriter writer= new StreamWriter(s);
sw.AutoFlush = true;
sw.WriteLine("hello world");`
In client side
TcpClient client = new TcpClient("localhost", 9999);
Stream s = client.GetStream();
Console.WriteLine("Connection successfully received");
StreamWriter writer = new StreamWriter(s);
StreamReader reader = new StreamReader(s);
sw.AutoFlush = true;
string dis=reader.readLine();
Console.WriteLine(dis);
Hope it will work now.
Related
Take a look at the following two programs:
//Server
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace MyServerProgram
{
class Program
{
static void Main(string[] args)
{
IPAddress ip = IPAddress.Parse("127.0.0.1");
int port = 2000;
TcpListener listener = new TcpListener(ip, port);
listener.Start();
TcpClient client = listener.AcceptTcpClient();
NetworkStream netStream = client.GetStream();
BinaryReader br = new BinaryReader(netStream);
try
{
while (client.Client.Connected)
{
string str = br.ReadString();
Console.WriteLine(str);
}
}
catch
{
br.Close();
netStream.Close();
client.Close();
listener.Stop();
}
}
}
}
//Client
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace MyClientProgram
{
class Program
{
static void Main(string[] args)
{
int port = 2000;
TcpClient client = new TcpClient("localhost", port);
NetworkStream netStream = client.GetStream();
BinaryWriter br = new BinaryWriter(netStream);
try
{
int i=1;
while (client.Client.Connected)
{
br.Write(i.ToString());
br.Flush();
i++;
int milliseconds = 2000;
System.Threading.Thread.Sleep(milliseconds);
}
}
catch
{
br.Close();
netStream.Close();
client.Close();
}
}
}
}
These programs are working fine.
Suppose, at this point of this program, I need the server to print a message on the screen as soon as a client gets connected to it, and, also when the client is disconnected.
How can I do that?
AcceptTcpClient blocks execution and starts waiting for connection. So right after it you can write message that client connected. Also you could write connected client address. Just for information, but sometimes it could be helpful.
TcpClient client = listener.AcceptTcpClient();
ShowMessage("Connected " + ((IPEndPoint)client.Client.RemoteEndPoint).Address);
For detect client disconnect you could catch exceptions. Change your catch like this:
catch (Exception ex) {
var inner = ex.InnerException as SocketException;
if (inner != null && inner.SocketErrorCode == SocketError.ConnectionReset)
ShowMessage("Disconnected");
else
ShowMessage(ex.Message);
...
Data received through a socket using JsonSerializer:
var stream = new NetworkStream(socket);
var serializer = new JsonSerializer();
using (var sr = new StreamReader(stream, new UTF8Encoding(), false))
using (var jsonTextReader = new JsonTextReader(sr))
{
var result = serializer.Deserialize(jsonTextReader).ToString();
}
But the call to the Deserialize hangs when the length of data received from the socket is about 2890 bytes.
It can be easily reproduced by using this code (when jsonArrayElementsCount = 192 - ok, when 193 - it hangs):
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Newtonsoft.Json;
namespace JsonNetHangsTest
{
class Program
{
static void Main(string[] args)
{
const int port = 11999;
const int jsonArrayElementsCount = 193;
var serverStartedEvent = new ManualResetEvent(false);
var clientReceivedEvent = new ManualResetEvent(false);
#region server
ThreadPool.QueueUserWorkItem(work =>
{
var server = new TcpListener(IPAddress.Parse("0.0.0.0"), port);
server.Start();
serverStartedEvent.Set();
var serverSocket = server.AcceptSocket();
var jsonString = "[\r\n" + String.Join(",", Enumerable.Repeat(" \"testdata\"\r\n", jsonArrayElementsCount)) + "]";
var bytes = new UTF8Encoding().GetBytes(jsonString);
serverSocket.Send(bytes);
Console.WriteLine("server send: " + bytes.Length);
clientReceivedEvent.WaitOne();
});
#endregion
serverStartedEvent.WaitOne();
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect("127.0.0.1", port);
var stream = new NetworkStream(socket);
var serializer = new JsonSerializer();
using (var sr = new StreamReader(stream, new UTF8Encoding(), false))
using (var jsonTextReader = new JsonTextReader(sr))
{
var result = serializer.Deserialize(jsonTextReader).ToString();
Console.WriteLine("client receive: " + new UTF8Encoding().GetBytes(result).Length);
}
clientReceivedEvent.Set();
Console.ReadKey();
}
}
}
What am I missing here?
Your problem is that the tail end of the JSON you are sending is getting buffered on the server side. From the docs:
There is also no guarantee that the data you send will appear on the network immediately. To increase network efficiency, the underlying system may delay transmission until a significant amount of outgoing data is collected. A successful completion of the Send method means that the underlying system has had room to buffer your data for a network send.
Thus you need to ensure the socket buffer gets flushed. However, there's no Flush() method on Socket. So, what to do?
The easiest thing to do is to dispose the socket as soon as you are done with it:
int byteCount;
using (var serverSocket = server.AcceptSocket())
{
byteCount = serverSocket.Send(bytes);
}
Console.WriteLine("server send: " + byteCount);
(Disposing of disposables as soon as you are done with them is a good idea always.)
Alternatively, wrap the serverSocket in a NetworkStream that owns the socket, then dispose of the stream (which amounts to the same thing):
var serverSocket = server.AcceptSocket();
using (var ns = new NetworkStream(serverSocket, true))
{
ns.Write(bytes, 0, bytes.Length);
}
(But see NetworkStream.Write vs. Socket.Send which suggests it's sometimes necessary to check the value returned from serverSocket.Send(bytes).)
You might want to consider handling SocketError.NoBufferSpaceAvailable. Here's one suggestion for how to do it: C# Examples: Socket Send and Receive [C#].
Here is a sample server and client code in c#. The server will send an array of string and the client will receive it and display and then the client will send an id and the server will receive it and display. But I am getting an exception in my the server while running both of them.
The exception is as follows:
An unhandled exception of type 'System.ObjectDisposedException' occurred in System.dll
Additional information: Cannot access a disposed object.
Client:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;
using System.Xml.Serialization;
namespace Client
{
class Program
{
static void Main(string[] args)
{
try
{
byte[] data = new byte[1024];
string stringData;
TcpClient tcpClient = new TcpClient("127.0.0.1", 1234);
NetworkStream ns = tcpClient.GetStream();
var serializer = new XmlSerializer(typeof(string[]));
var stringArr = (string[])serializer.Deserialize(tcpClient.GetStream());
foreach (string s in stringArr)
{
Console.WriteLine(s);
}
string input = Console.ReadLine();
ns.Write(Encoding.ASCII.GetBytes(input), 0, input.Length);
ns.Flush();
}
catch (Exception e)
{
Console.Write(e.Message);
}
Console.Read();
}
}
}
Server:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;
using System.Xml.Serialization;
namespace server
{
class Program
{
static void Main(string[] args)
{
TcpListener tcpListener = new TcpListener(IPAddress.Any, 1234);
tcpListener.Start();
while (true)
{
TcpClient tcpClient = tcpListener.AcceptTcpClient();
byte[] data = new byte[1024];
NetworkStream ns = tcpClient.GetStream();
string[] arr1 = new string[] { "one", "two", "three" };
var serializer = new XmlSerializer(typeof(string[]));
serializer.Serialize(tcpClient.GetStream(), arr1);
tcpClient.Close();
int recv = ns.Read(data, 0, data.Length); //getting exception in this line
string id = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine(id);
}
}
}
}
Is there anything wrong?
What will I need to change to avoid this exception?
Once you call
tcpClient.Close();
it cleans up resources associated with it, including disposing ns.
The following line
int recv = ns.Read(data, 0, data.Length); //getting exception in this line
attempts to read from ns after you just (indirectly) disposed of it.
Do not close the connection until you are done with it. Also, use the using keyword instead of explicitly closing the connection, as it will ensure proper cleanup even if an exception is thrown.
I wrote a C# TCP Server that runs on my desktop, while I have a client running on my windows phone. It works great, the client can connect to the server. But I am trying to make it so the server can receive messages from the client. When I run it, the server just receives a number when I am sending a string.
Here is my server code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;
namespace TCPServer
{
class Server
{
private TcpListener tcpListener;
private Thread listenThread;
public Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 80);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
TcpClient client = this.tcpListener.AcceptTcpClient();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
Console.WriteLine("Got connection");
StreamReader clientStreamReader = new StreamReader(clientStream);
Console.WriteLine(clientStreamReader.Read());
}
}
}
Here is the client code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace NetworkingTesting
{
class Client
{
Socket socket = null;
static ManualResetEvent clientDone = new ManualResetEvent(false);
const int TIMEOUT_MILLISECONDS = 5000;
const int MAX_BUFFER_SIZE = 2048;
DnsEndPoint hostEntry;
public string Connect(string hostName, int portNumber)
{
string result = string.Empty;
hostEntry = new DnsEndPoint(hostName, portNumber);
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
socketEventArg.RemoteEndPoint = hostEntry;
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
{
result = e.SocketError.ToString();
clientDone.Set();
});
clientDone.Reset();
socket.ConnectAsync(socketEventArg);
clientDone.WaitOne(TIMEOUT_MILLISECONDS);
return result;
}
public void SendToServer(string message)
{
SocketAsyncEventArgs asyncEvent = new SocketAsyncEventArgs { RemoteEndPoint = hostEntry};
Byte[] buffer = Encoding.UTF8.GetBytes(message + Environment.NewLine);
asyncEvent.SetBuffer(buffer, 0, buffer.Length);
socket.SendAsync(asyncEvent);
}
}
}
In my main client class, I have: client.SendToServer("hello!");
When I run the server and run the client the server detects the client but receives "104" instead of "Hello". Could anybody explain why this is happening and maybe provide a solution to the problem?
When you're doing clientStreamReader.Read() you're just reading one char as int from the stream. Check the doc here.
That's why you get only a number.
You need a delimeter to each message to know where it ends, \r\n is often used.
Here a sample to make your server receive your hello! String :
In your client Code
client.SendToServer("hello!" + "\r\n");
In your server Code
Console.WriteLine(clientStreamReader.ReadLine()); // Which should print hello!
I am building a bare bones program that simple delivers a message from server to client.
Now i am successfully able to establish connection between the server and client, however the client program is unable to read from the stream. Here's my code.
Code for server program
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Net.Sockets;
namespace chat_client_console
{
class Program
{
static TcpListener listener;
static void Main(string[] args)
{
string name = Dns.GetHostName();
IPAddress[] address = Dns.GetHostAddresses(name);
/*
foreach(IPAddress addr in address)
{
Console.WriteLine(addr);
}*/
Console.WriteLine(address[1].ToString());
listener = new TcpListener(address[1], 2055);
listener.Start();
Socket soc = listener.AcceptSocket();
Console.WriteLine("Connection successful");
Stream s = new NetworkStream(soc);
StreamReader sr = new StreamReader(s);
StreamWriter sw = new StreamWriter(s);
sw.AutoFlush = true;
sw.Write("A test message");
Console.WriteLine("Test message delivered. Now ending the program");
/*
string name = Dns.GetHostName();
Console.WriteLine(name);
//IPHostEntry ip = Dns.GetHostEntry(name);
//Console.WriteLine(ip.AddressList[0].ToString());
IPAddress[] adr=Dns.GetHostAddresses(name);
foreach (IPAddress adress in adr)
{
Console.WriteLine(adress);
}
*/
Console.ReadLine();
}
}
}
and here's the code from the client program
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net.Sockets;
namespace chat_client_console_client
{
class Program
{
static void Main(string[] args)
{
string display;
TcpClient client = new TcpClient("localhost", 2055);
Stream s = client.GetStream();
Console.WriteLine("Connection successfully received");
StreamWriter sw = new StreamWriter(s);
StreamReader sr = new StreamReader(s);
sw.AutoFlush = true;
while (true)
{
display = sr.ReadLine();
Console.WriteLine("Reading stream");
if (display == "")
{
Console.WriteLine("breaking stream");
break;
}
}
Console.WriteLine(display);
}
}
}
now i am successfully able to establish connection between the programs as indicated by various check messages. The server program is also successfully able to send the data into the stream.
However the client program is unable to read data from the stream. It seems to be stuck at readline() function.
Now i have been banging my head against the wall on this problem for hours now and would be greatly thankful if somebody is able to help me.
Look at your server:
sw.AutoFlush = true;
sw.Write("A test message");
You're never writing a line break, which is what the client is waiting to see.