bellow is my code for server, which runs successfully but small problem is, when i send data from client from twice it accepts once.
e.g. if i run this server and client also togethor; first time it accepts data from client, second time when again i ping from client side it does not accept data third time when i ping from client side it accepts data, fourth time when i ping from client it does not accept data, fifth time when i ping from client it accepts data, and so on.....
thanking you in advanced.
class Program
{
//static byte[] Buffer { get; set; }
//static Socket sck;
static void Main(string[] args)
{
while (true)
{
Socket sck;
sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sck.Bind(new IPEndPoint(0, 2000));
sck.Listen(10);
Socket accepted = sck.Accept();
byte [] Buffer = new byte[accepted.SendBufferSize];
int bytesRead = accepted.Receive(Buffer);
byte[] formatted = new byte[30];
for (int i = 0; i < 30; i++)
{
formatted[i] = Buffer[i];
}
string strData = Encoding.ASCII.GetString(formatted);
Console.Write(strData + "\r\n");
sck.Close();
accepted.Close();
}
}
}
This is not how you normally code a server. Usually, the listener stays up and just accepts new connections and closes them when done. It's possible that on the second attempt the client connects to your old listener just before you close it. Try keeping the listener open or else close the listener as soon as you accept a connection.
You need a TcpListner
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener(v=vs.71).aspx
Also, to handle many requests you need the server the process multiple requests on different threads. You'll need a thread pool. Look at ThreadPool.QueueUserWorkitem.
Here's a more complete C# TCP server example using that:
http://www.codeproject.com/KB/IP/dotnettcp.aspx
You need run the server into Thread
public void StartListener()
{
while (true)
{
mySocket = myListener.AcceptSocket();
Console.WriteLine("\r\nsocket type = {0}", mySocket.SocketType);
if (mySocket.Connected)
{
byte[] receive = new byte[1024];
mySocket.Receive(receive, 1024, 0);
string sBuffer = Encoding.ASCII.GetString(receive);
}
}
}
Then:
IPAddress IPaddress = Dns.Resolve(Dns.GetHostName()).AddressList[0];
TcpListener myListener = new TcpListener(IPaddress, 50);
myListener.Start();
Thread th = new Thread(new ThreadStart(StartListener));
th.Start();
More info:
TcpListener Class
Thread
Related
I made a little experiment where a server send continually a message to a client until a second client be connected. Testing with telnet, the first client receive the message continually, but when the second client connects, the client counter (nClients) increments in the second client thread, but not in the first one. So with a third and a fourth clients an so on. Variable nClients still being 1 in the first client but is incremented in the next ones.
The code:
class Program
{
volatile static int nClients = 0;
static void clientThread(object socket)
{
Socket client = (Socket)socket;
IPEndPoint ieCliente = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("IP: {0} port: {1}", ieCliente.Address, ieCliente.Port);
nClients++;
Console.WriteLine(nClients);
using (NetworkStream ns = new NetworkStream(client))
using (StreamWriter sw = new StreamWriter(ns))
{
sw.WriteLine("Welcome");
sw.Flush();
while (nClients < 2)
{
sw.WriteLine($"Waiting clients... now {nClients} connected");
sw.Flush();
//Thread.Sleep(100);
}
sw.WriteLine($"{nClients} clients");
sw.Flush();
}
client.Close();
}
static void Main(string[] args)
{
int port = 31416;
IPEndPoint ie = null;
ie = new IPEndPoint(IPAddress.Any, port);
using (Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
s.Bind(ie);
s.Listen(5);
Console.WriteLine($"Server listening at port: {ie.Port}");
while (true)
{
Socket cliente = s.Accept();
Thread th= new Thread(clientThread);
th.Start(cliente);
}
}
}
}
If I add an Thread.Sleep() into the loop (or even a Console.Writeline()) it works.
Why does the first thread not detect the change of nClients.
Actualization:
Following the feeedback recommendations, I was trying de Interlocked.Increment() and Volatile.Read() but the problem persist. My code again with these changes.
class Program
{
static int nClients = 0;
static void clientThread(object socket)
{
Socket client = (Socket)socket;
IPEndPoint ieCliente = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("IP: {0} port: {1}", ieCliente.Address, ieCliente.Port);
Interlocked.Increment(ref nClients);
Console.WriteLine(Volatile.Read(ref nClients));
using (NetworkStream ns = new NetworkStream(client))
using (StreamWriter sw = new StreamWriter(ns))
{
sw.WriteLine("Welcome");
sw.Flush();
while (Volatile.Read(ref nClients) < 2)
{
sw.WriteLine($"Waiting clients... now {Volatile.Read(ref nClients)} connected");
sw.Flush();
//Thread.Sleep(100);
}
sw.WriteLine($"{Volatile.Read(ref nClients)} clients");
sw.Flush();
}
client.Close();
}
static void Main(string[] args)
{
int port = 31416;
IPEndPoint ie = null;
ie = new IPEndPoint(IPAddress.Any, port);
using (Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
s.Bind(ie);
s.Listen(5);
Console.WriteLine($"Server listening at port: {ie.Port}");
while (true)
{
Socket cliente = s.Accept();
Thread th = new Thread(clientThread);
th.Start(cliente);
}
}
}
}
And here a video showing this behavior. And a bonus: when I close abruptly the server, sometimes the client continue in the loop.
I think that for some reason when I close the server, Windows close the process but the threads memory is not released and continue running.
The problem is here:
nClients++;
This is being executed by more than one thread simultaneously, and it is not threadsafe.
The reason why is as follows. The code is (logically) equivalent to the following:
int temp = nClients + 1; // [A]
nClients = temp; // [B]
So lets imagine that nClients is 0. Thread #1 executes line [A] and thus temp is 1. Now imagine that before thread #1 has executed [B], thread #2 comes along and executes [A]. Thread #2's value for temp is also 1, because nothing has changed the value of nClients yet.
Now both threads continue, and they both set nClients to temp, which is 1.
Oops! An increment went missing.
That's what's happening. (Well, this is actually a gross simplification, but it's a good way to understand how it can go wrong.)
To fix it you can either put a lock around the incrementing code, or (simpler and more efficient) use Interlocked.Increment():
Interlocked.Increment(ref nClients);
i made a program where there is some data that i want to send several times per second through a Socket. This code bellow (client side) works fine and its called 60 times per second, but i was thinking that maybe, close the socket every time i want to send some data is not the best option or it is inefficient. The problem is that until i dont close the socket, the server side dont read the data in the socket.
Client side in C# (the function Update is called several times per second):
void Update()
{
soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
string server = "127.0.0.1";
IPAddress ipAdd = IPAddress.Parse(server);
IPEndPoint remoteEP = new IPEndPoint(ipAdd, 3456);
soc.Connect(remoteEP);
byte[] msg = System.Text.Encoding.ASCII.GetBytes("velocidad(k/h): " + telemetria.vehicle.data.Get(Channel.Vehicle, VehicleData.Speed)*3.6f/1000.0f);
soc.Send(msg);
soc.Close();
}
Server side in Java
public static void main(String[] args) throws IOException{
ServerSocket ss = new ServerSocket(3456);
while(true) {
Socket s = ss.accept();
InputStreamReader in = new InputStreamReader(s.getInputStream());
BufferedReader bf = new BufferedReader(in);
String str = bf.readLine();
System.out.println(str);
}
}
I am having a weird problem where I am making a chat connection with TCPListeners and sockets. For some reason when a client "connects" to the server it will show they have connected twice. Also what is weird once all of the users have connected I will send out a message to all of them. They will respond back with it acknowledged and state that their chat has started.
Things I am noticing with how i have it setup:
It appears according to the log that the user "connects" twice the second "connect occurs once it hits the white(true) loop.
When they send over the acknowledgement back to the server not all of the data is getting sent over. If I do a thread sleep on the client it does appear to start working but it is still inconsistent.
Here is the code:
Server:
private TcpListener tcpListener;
private Thread listen;
private TcpListener tcpUser1, tcpUser2,tcpUser3;
NetworkStream User1Stream,User2Stream,User3Stream;
public event NetworkMessageStringDelegate MessageFromUser;
TcpClient client;
public void start(string ip){
IpHostEntry host = dns.GetHostEntry(dns.GetHostName());
IpAddress[] ip = host.AddressList;
serverStatus = "Server started with IP of: " + ip;
Thread.Sleep(1);
tcpUser1 = new TcpListener(IpAddress.Any, 4001);
listen = new Thread(new ThreadStart(() => ListenUser1(tcpUser1)));
listen.Start();
Thread.Sleep(1);
tcpUser2 = new TcpListener(IpAddress.Any, 4002);
listen = new Thread(new ThreadStart(() => ListenUser2(tcpUser2)));
listen.Start();
Thread.Sleep(1);
tcpUser3 = new TcpListener(IpAddress.Any, 4003);
listen = new Thread(new ThreadStart(() => ListenUser3(tcpUser3)));
listen.Start();
Thread.Sleep(1);
}
public void ListenUser3(TcpListener tmp){
tcpListener = (TcpListener)tmp;
Socket = "Listening for User3";
tcpUser3.Start();
Thread.Sleep(2);
while(true){
user3 = this.tcpListener.AcceptTcpClient();
Thread user3Thread = new Thread(new ParmeterizedThreadStart(receiveUser3Data));
user3Thread.Start(user3);
}
}
//Mostly from MS documenation
private void receiveUser3Data(object client){
client = (TcpClient)client;
User3Stream = client.getStream();
Socket = "Connected to User: " + client.Client.RemoteEndPoint.toString();
byte[] message = new byte[4096];
int total;
//This is the line it will display the socket message Twice. "Connected to User...."
while(true){
total = 0;
try{
do{
total = User3Stream.Read(message,0,4096);
}
while(user3.DataAvailable);
}
catch()
{
Socket = "Error State";
}
}
byte[] infoPacket = new byte[total];
Array.ConstrainedCopy(message,0,infoPacket,total);
if(MessageFromUser3 != null){
MessageFromUser?.Invoke(packet);
}
}
Client:
public void ConfigureUser3(){
try{
socket = new Network.TCPIPClient();
socket.ReceiveMessage() = new Newowrk.TCPIPClient.NetworkMessageStringDelgate(MessageFromserver);
socket.SendMessage() = new Newowrk.TCPIPClient.NetworkMessageStringDelgate(sendMessage);
userThread = new Thread(() => socket.Start("0.0.0.0),4054));
userThread.Start();
}
catch(Exception ex){
}
}
//This is where if I sleep it will send but it is still inconsident
private void SendMEssageToSever(object tmpVal){
object[] sendMessage = tmpVal as object[];
string tmpSendValue = tmpVal[0].ToString();
byte sendValue = Coonvert.ToByte(tmpVal[1]);
packetData[0] = 0;
packetData[1] = sendValue;
packetData[2] = Convert.ToByte(tmpSendValue);
socket.sendMessage = packetData;
}
private voide sendMessage(byte[] userMessage){
try{
if(socket){
outputMessage.Enqueue(userMessage);
while(outputMessage.Count > 0){
Byte[] sendMessage = outputMessage.Dequeue();
string message = ascII.GetString(sendMessage);
if(socket.Connected){
lock(socket){
socket.Send(sendMessage,sendMessage.length,0);
}
}
}
}
}
catch(Exception ex)
}
This code is essentially repeated for all users that are connected to the server.
The TcpListener has asynchronous methods like BeginAcceptTcpClient.
TcpClient.GetStream() (which is a NetworkStream) also has asynchronous methods like BeginRead.
I suggest you change your server code to use these and to store the user state in a class and pass this class to and fro between Begin* and End* methods.
You can support N number of users then, and don't have to repeat code for each user. You also don't have to have 3 different listeners for 3 connections. Have just one listener and accept clients over this one. The rest is two-way communication via TcpClient.GetStream()
Here is a minimal server example which listens on port 9988 (for only LoopBack, which means the local machine). You can of course change this.
There is no client example here. Only the server. Just copy/paste the code into your program.cs file in a console application.
I hope the comments are sufficient to explain the code.
I hope also, that this helps.
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
class Program
{
/// <summary>
/// Contains the state for a client connection
/// </summary>
public class ClientState
{
public const int ReceiveBufferSize = 8192;
// The buffer to receive in
internal byte[] receiveBuffer = new byte[ReceiveBufferSize];
// The TcpClient instance representing the remote end (connected client)
public TcpClient TcpClient { get; set; }
public byte[] GetReceiveBuffer()
{
return receiveBuffer;
}
}
// This method is invoked when data is received from a client
static void OnReceive(IAsyncResult asyncResult)
{
// The state parameter passed to the BeginRead method
// is provided here in the asyncResult.AsyncState property
ClientState clientState = asyncResult.AsyncState as ClientState;
int numberOfBytesReceived = clientState.TcpClient.GetStream().EndRead(asyncResult);
if (numberOfBytesReceived == 0)
{
// This means that the transmission is over
Console.WriteLine("Client disconnect: {0}", clientState.TcpClient.Client.RemoteEndPoint);
return;
}
// Now the receiveBuffer is filled with <numberOfBytesReceived> bytes received from the client.
// Do whatever is needed here.
Console.WriteLine("Received {0} bytes from {1}", numberOfBytesReceived, clientState.TcpClient.Client.RemoteEndPoint);
// We are also sending some information back:
StreamWriter streamWriter = new StreamWriter(clientState.TcpClient.GetStream());
streamWriter.WriteLine("The server has received {0} bytes from you! Keep up the good job!", numberOfBytesReceived);
streamWriter.Flush();
// Begin read again
clientState.TcpClient.GetStream().BeginRead(clientState.GetReceiveBuffer(), 0, ClientState.ReceiveBufferSize, OnReceive, clientState);
}
// This method is invoked when a new client connects
static void OnConnect(IAsyncResult asyncResult)
{
// The state parameter passed to the BeginAcceptTcpClient method
// is provided here in the asyncResult.AsyncState property
TcpListener tcpListener = asyncResult.AsyncState as TcpListener;
// Accept the TcpClient:
TcpClient newClient = tcpListener.EndAcceptTcpClient(asyncResult);
// Immediately begin accept a new tcp client.
// We do not want to cause any latency for new connection requests
tcpListener.BeginAcceptTcpClient(OnConnect, tcpListener);
// Create the client state to store information aboutn the client connection
ClientState clientState = new ClientState()
{
TcpClient = newClient
};
Console.WriteLine("A new client has connected. IP Address: {0}", newClient.Client.RemoteEndPoint);
// Start receiving data from the client
// Please note that we are passing the buffer (byte[]) of the client state
// We are also passing the clientState instance as the state parameter
// this state parameter is retrieved using asyncResult.AsyncState in the asynchronous callback (OnReceive)
newClient.GetStream().BeginRead(clientState.GetReceiveBuffer(), 0, ClientState.ReceiveBufferSize, OnReceive, clientState);
// Nothing else to do.
// The rest of the communication process will be handled by OnReceive()
}
static void Main()
{
// Start a tcp listener
TcpListener tcpListener = new TcpListener(IPAddress.Loopback, 9988);
tcpListener.Start();
// Begin accept a new tcp client, pass the listener as the state
// The state is retrieved using asyncResult.AsyncState in the asynchronous callback (OnConnect)
tcpListener.BeginAcceptTcpClient(OnConnect, tcpListener);
// That's it. We don't need anything else here, except wait and see.
Console.WriteLine("Server is listening on port 9988. Press enter to stop.");
Console.ReadLine();
}
}
I have this simple tcp server class
class Server
{
private TcpListener tcpListener;
private Thread listenThread;
public Server()
{
this.tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
Console.WriteLine("Hello");
}
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));
Console.WriteLine("New connexion");
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
Console.WriteLine("Got Stream");
byte[] message = new byte[4096];
int bytesRead;
Console.WriteLine("Initializing..");
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
Console.WriteLine("Reading..");
bytesRead = clientStream.Read(message, 0, 4096);
Console.WriteLine("Received something");
}
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();
Console.WriteLine(encoder.GetString(message, 0, bytesRead));
}
tcpClient.Close();
}
}
I simply call it in the main function like this :
Server server = new Server();
And in a separate client program I have this class
class TheClient
{
public void ConnectV2()
{
TcpClient client = new TcpClient();
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);
client.Connect(serverEndPoint);
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
for (int i = 0; i < 20; i++)
{
byte[] buffer = encoder.GetBytes("Hello Server! " + i.ToString() + " ");
Console.WriteLine("Processing..");
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
Console.WriteLine("Hello Server sent");
}
}
}
I call it in the main function like
TheClient tc = new TheClient();
tc.ConnectV2();
My problem is that the server program seems slower than the client, he don't react before the 13th, or more, message from the client :
[I can't post images because of reputation]
It reads the first dozen of messages in one go, and then reads the others one by one.
And if I make the server emit first, the client receive the message, but they both stop, like if both wait for the other to send something.
Can someone explain me this behavior ? How can I control and synchronize it ?
TCP is not message based. It provides a stream of bytes. It is your responsibility to separate messages. Also note, that you might receive only a part of a message in one Read call.
Here's a simple way to do that: Send the messages as individual lines. Possibly using StreamWriter. Receive the messages using StreamReader.ReadLine().
That way you can also use a more sane encoding such as Encoding.UTF8.
Besides that your code is actually fine and workable. It is extremely rare to see almost working TCP code on Stack Overflow. Most code is horribly broken. Congratulations.
It's because that your client AP is always sending data ,but your server AP cannot receive those data right away. So,those data stacked in buffer and then server AP receive all at once.
You can try:
Set fixed lengths when you send or receive data.
or
Receive and split data.
This is my Server App:
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();
while (true)
{
Console.WriteLine("Server is listening on " + listener.LocalEndpoint);
Console.WriteLine("Waiting for a connection...");
Socket client = listener.AcceptSocket();
Console.WriteLine("Connection accepted.");
Console.WriteLine("Reading data...");
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]));
Console.WriteLine();
client.Close();
}
listener.Stop();
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.StackTrace);
Console.ReadLine();
}
}
As you can see , it always listens while working , but I would like to specify that I want the app be able to listen and to have multiple connections support in the same time.
How could I modify this to constantly listen while also accepting the multiple connections?
The socket on which you want to listen for incoming connections is commonly referred to as the listening socket.
When the listening socket acknowledges an incoming connection, a socket that commonly referred to as a child socket is created that effectively represents the remote endpoint.
In order to handle multiple client connections simultaneously, you will need to spawn a new thread for each child socket on which the server will receive and handle data.
Doing so will allow for the listening socket to accept and handle multiple connections as the thread on which you are listening will no longer be blocking or waiting while you wait for the incoming data.
while (true)
{
Socket client = listener.AcceptSocket();
Console.WriteLine("Connection accepted.");
var childSocketThread = new Thread(() =>
{
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]));
}
Console.WriteLine();
client.Close();
});
childSocketThread.Start();
}
I had a similar problem today, and solved it like this:
while (listen) // <--- boolean flag to exit loop
{
if (listener.Pending())
{
Thread tmp_thread = new Thread(new ThreadStart(() =>
{
string msg = null;
TcpClient clt = listener.AcceptTcpClient();
using (NetworkStream ns = clt.GetStream())
using (StreamReader sr = new StreamReader(ns))
{
msg = sr.ReadToEnd();
}
Console.WriteLine("Received new message (" + msg.Length + " bytes):\n" + msg);
}
tmp_thread.Start();
}
else
{
Thread.Sleep(100); //<--- timeout
}
}
My loop did not get stuck on waiting for a connection and it did accept multiple connections.
EDIT: The following code snippet is the async-equivalent using Tasks instead of Threads. Please note that the code contains C#-8 constructs.
private static TcpListener listener = .....;
private static bool listen = true; // <--- boolean flag to exit loop
private static async Task HandleClient(TcpClient clt)
{
using NetworkStream ns = clt.GetStream();
using StreamReader sr = new StreamReader(ns);
string msg = await sr.ReadToEndAsync();
Console.WriteLine($"Received new message ({msg.Length} bytes):\n{msg}");
}
public static async void Main()
{
while (listen)
if (listener.Pending())
await HandleClient(await listener.AcceptTcpClientAsync());
else
await Task.Delay(100); //<--- timeout
}
Basic idea is, there is listener socket always listening on a given IP and port number. When ever there is connection request, listener accept the connection and remote end point is taken with tcpclient object till connection is closed or lost.