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!
Related
me and my friends are currently trying to build a chat application with c sharp in visual studio .
while doing that we bumped into the words "client network" and "server network" .
I ve been told that those are two dll files that provides a connection between my client , server and database . Can anyone explain to me what should these dll files contain and how to they contribute to our chat application ( I am still a beginner )
Thank you so much !
According to your description, you want to solve the communication between the client and the server.
I recommend that you use socket to realize the connection between server and client, and
create two DLL files to facilitate program reference.
It will be explained in detail below.
(1) ClientCommunication.dll
1: Establish a Socket object;
2: Use the Connect() method of the socket object to send the connection request to the server with the EndPoint object created above as a parameter;
3: If the connection is successful, use the Send() method of the socket object to send information to the server;
4: Use the Receive() method of the socket object to receive the information sent by the server;
5: Be sure to close the socket after the communication is over
(2) ServerCommunication.dll
1: Establish a Socket object;
2: Bind EndPoint with the Bind() method of the socket object;
3: Use the Listen() method of the socket object to start listening;
4: Accept the connection to the client, use the socket object's Accept() method to create a new socket object for communicating with the requesting client;
5: Use the new socket object to receive and send messages.
ServerCommunication.dll contains ServerSocket.cs
ServerSocket.cs code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ServerCommunication
{
public class ServerSocket
{
static Socket serverSocket;
public static void StartListening(IPAddress ip, int port)
{
serverSocket = new Socket(SocketType.Stream, ProtocolType.Tcp);
IPEndPoint point = new IPEndPoint(ip, port);
serverSocket.Bind(point);
Console.WriteLine("{0}Listen Success", serverSocket.LocalEndPoint.ToString());
serverSocket.Listen(10);
Thread myThread = new Thread(ListenClientConnect);
myThread.Start();
Console.ReadLine();
}
static void ListenClientConnect()
{
while (true)
{
Socket clientSocket = serverSocket.Accept();
clientSocket.Send(Encoding.ASCII.GetBytes("Server Say Hello"));
Thread receiveThread = new Thread(ReceiveMessage);
receiveThread.Start(clientSocket);
}
}
static void ReceiveMessage(object clientSocket)
{
Socket myClientSocket = (Socket)clientSocket;
while (true)
{
try
{
//clientSocket accept
byte[] result = new byte[1024];
int receiveNumber = myClientSocket.Receive(result);
Console.WriteLine("Receive client{0}news{1}", myClientSocket.RemoteEndPoint.ToString(), Encoding.ASCII.GetString(result, 0, receiveNumber));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
myClientSocket.Shutdown(SocketShutdown.Both);
myClientSocket.Close();
break;
}
}
}
}
}
ClientCommunication.dll contains ClientSocket.cs
ClientSocket.cs code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ClientCommunication
{
public class ClientSocket
{
static byte[] result = new byte[1024];
public static void StartClient(IPAddress ip, int port)
{
Socket socketClient = new Socket(SocketType.Stream, ProtocolType.Tcp);
IPEndPoint point = new IPEndPoint(ip, port);
try
{
socketClient.Connect(point);
Console.WriteLine("Successfully connected to server!");
}
catch
{
Console.WriteLine("Failed to connect to the server, please press enter to exit!");
return;
}
//clientSocket accept
int receiveLength = socketClient.Receive(result);
Console.WriteLine("Receive server message:{0}", Encoding.ASCII.GetString(result, 0, receiveLength));
// clientSocket send
try
{
Thread.Sleep(1000);
string sendMessage = "client send Message Hellp" + DateTime.Now;
socketClient.Send(Encoding.ASCII.GetBytes(sendMessage));
Console.WriteLine("Send message to server:{0}" + sendMessage);
}
catch
{
socketClient.Shutdown(SocketShutdown.Both);
socketClient.Close();
}
Console.WriteLine("After sending, press enter to exit");
Console.ReadLine();
}
}
}
The specific use is as follows:
Server,cs code:
using ServerCommunication;
using System.Net;
namespace Server
{
class Server
{
static void Main(string[] args)
{
IPAddress ip = IPAddress.Parse("127.0.0.1");
int port = 8885;
ServerSocket.StartListening(ip,port);
}
}
}
Client.cs code:
using ClientCommunication;
using System.Net;
namespace Client
{
class Client
{
static void Main(string[] args)
{
IPAddress ip = IPAddress.Parse("127.0.0.1");
int port = 8885;
ClientSocket.StartClient(ip,port);
}
}
}
Operation results:
Server:
Client:
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);
...
I'm trying to figure out how I can send & receive data via the UDP protocol using C# as a client, and having a JS server running that will transmit a "response" packet for testing purposes.
Below is the UDP class that I made for testing, it's simply just 2 threads:
One that read the received data from UDP and another thread for sending data.
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace UDPTesting {
class UDPHandler {
private int receivePort, sendPort;
private string serverIP;
private IPEndPoint sendEndPoint, receiveEndPoint;
public UDPHandler(string serverIP, int receivePort, int sendPort) {
this.serverIP = serverIP;
this.receivePort = receivePort;
this.sendPort = sendPort;
this.sendEndPoint = new IPEndPoint(IPAddress.Parse(this.serverIP), this.sendPort);
this.receiveEndPoint = new IPEndPoint(IPAddress.Parse(this.serverIP), this.receivePort);
this.readerUdpClient();
this.senderUdpClient();
}
void readerUdpClient() {
UdpClient readerClient = new UdpClient();
IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Any, 3000);
readerClient.Client.Bind(localEndpoint); //Tried both Connect and Bind
//readerClient.Connect(this.receiveEndPoint);
Thread t = new Thread(() => {
Console.WriteLine("Awaiting data from server...");
var remoteEP = new IPEndPoint(IPAddress.Any, 3000);
byte[] bytesReceived = readerClient.Receive(ref remoteEP);
//The above throws: System.InvalidOperationException: 'You must call the Bind method before performing this operation'
Console.WriteLine("Received data from " + remoteEP.ToString());
});
t.Start();
}
void senderUdpClient() {
UdpClient senderClient = new UdpClient();
senderClient.Connect(this.sendEndPoint);
string sendString = "1;2;3";
byte[] bytes = toBytes(sendString);
Thread t = new Thread(() => {
while (true) {
senderClient.Send(bytes, bytes.Length);
Thread.Sleep(1000);
}
});
t.Start();
}
public byte[] toBytes(string text) {
return Encoding.UTF8.GetBytes(text);
}
public string fromBytes(byte[] bytes) {
return Encoding.UTF8.GetString(bytes);
}
}
}
Additionally my "main" for my program is this:
using System;
using System.Threading;
namespace UDPTesting {
class Program {
static void Main(string[] args) {
string serverIP = "46.101.102.243";
int sendPort = 41234;
int receivePort = 3000;
UDPHandler handler = new UDPHandler(serverIP, receivePort, sendPort);
}
}
}
How can I read the response that the server sends in the client, at the same time as I send data from the client to the server?
We tested it individually:
1) Sending a UDP packet from client -> server works, as I can see that the server receives the packet.
2) Sending a UDP packet from server -> client works, as I can see the client receives the packet.
3) When the client tries to send and read simultaneously, it will send data to the server, but will not read the response.
Any help would be greatly appreciated!
Your receiving function should work like this
void readerUdpClient()
{
new Thread(() => {
UdpClient readerClient = new UdpClient(receivePort);
Console.WriteLine("Awaiting data from server...");
var remoteEP = new IPEndPoint(IPAddress.Any, 0);
byte[] bytesReceived = readerClient.Receive(ref remoteEP);
Console.WriteLine($"Received {bytesReceived.Length} bytes from {remoteEP}");
}).Start();
}
The UdpClient constructor that takes a port automatically binds the local end point for you.
I am a newbie in C#, and I have developed a Socket program.
private static void SetupServer()
{
Console.WriteLine("Setting up server...");
serverSocket.Bind(new IPEndPoint(IPAddress.Any, 100));
serverSocket.Listen(1);
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
But after server response a client, server is closed and not listen any time. How should I do to reset server after calling Listen(backlog) to maintain server for a long time?
This is my code in ClientSide:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace PC_Client
{
public partial class Form1 : Form
{
private static Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public Form1()
{
InitializeComponent();
Console.ReadLine();
}
private void SendLoop()
{
string req = txtRequest.Text;
byte[] buffer = Encoding.ASCII.GetBytes(req);
clientSocket.Send(buffer);
byte[] receiveBuf = new byte[1024];
int rec = clientSocket.Receive(receiveBuf);
byte[] data = new byte[rec];
Array.Copy(receiveBuf, data, rec);
Console.WriteLine("Received: " + Encoding.ASCII.GetString(data));
}
private void LoopConnect()
{
int attempts = 0;
while(!clientSocket.Connected)
{
try
{
attempts++;
clientSocket.Connect(IPAddress.Loopback, 100);
}
catch (SocketException)
{
Console.WriteLine("Connection attempts: " + attempts.ToString());
}
}
//Console.Clear();
Console.WriteLine("Connected");
}
private void button1_Click(object sender, EventArgs e)
{
SendLoop();
}
}
}
I'm not sure about the particulars of C#, but in general, you want to wrap your accept call in a loop like so:
while(true) {
clientSocket = serverSocket.accept();
respond to socket in background thread
}
This way, your main thread will always be able to listen for sockets (because its wrapped in a while loop, and continues to accept new connections) while also not being blocked while handling a client request (because the client socket is handled in a background thread)
I found this great code on MSDN for a UDP Client/Server connection, however the client can only send to the server, it cant reply back. How can I make this so the server can respond to the client that send the message.
The Server
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Security.Cryptography;
namespace UDP_Server
{
class Program
{
private const int listenPort = 11000;
private static void StartListener()
{
bool done = false;
UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
try
{
while (!done)
{
Console.WriteLine("Waiting for broadcast");
byte[] bytes = listener.Receive(ref groupEP);
Console.WriteLine("Received broadcast from {0} :\n {1}\n",groupEP.ToString(), Encoding.ASCII.GetString(bytes, 0, bytes.Length));
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
listener.Close();
}
}
public static int Main()
{
StartListener();
return 0;
}
}
}
And the client
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Security.Cryptography;
namespace UDP_Client
{
class Program
{
static void Main(string[] args)
{
Send("TEST STRING");
Console.Read();
}
static void Send(string Message)
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress broadcast = IPAddress.Parse("10.1.10.117");
byte[] sendbuf = Encoding.ASCII.GetBytes(Message);
IPEndPoint ep = new IPEndPoint(broadcast, 11000);
s.SendTo(sendbuf, ep);
}
}
}
Just do it the other way round. Call StartListener on the client and it can receive udp data like a server.
On your server just send data with the clients code.
It's the same code, just with reversed roles. The client needs to listen on some port, and the server sends the message to the client's endpoint instead of the broadcast address.