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);
Related
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 am trying to implement a TCP forwarder in C#. Specifically the application:
Listens to a TCP port and wait for a client,
When a client is connected, connects to a remote host,
Waits for incoming data on the both connections and exchange the data between two endpoints (acts as an proxy),
Closes one connection when the other one get closed by an endpoint.
I have adapted Simple TCP Forwader (by Garcia) to forward a range of ports so that
TCPForwarder.exe 10.1.1.1 192.168.1.100 1000 1100 2000
will forward any packets received on 10.1.1.1 on port 1000-1100 to remote host 192.168.1.100 port 2000-2100. I have employed this to expose a FTP server that is behind a NAT.
By running the above command, the client is able to connect to the FTP server and the following pattern in outputted to the console which is expected (refer to code):
0 StartReceive: BeginReceive
1 StartReceive: BeginReceive
1 OnDataReceive: EndReceive
1 OnDataReceive: BeginReceive
1 OnDataReceive: EndReceive
1 OnDataReceive: Close (0 read)
0 OnDataReceive: EndReceive
0 OnDataReceive: Close (exception)
But after successfully connecting for several times (pressing F5 in Filezilla), no further response is received from TCPForwarder (and FTP Server).
There seems to be two problems with my implementation that I cannot debug:
In that situation, the BeginReceive in StartReceive method gets called, but no data is received from the FTP server. I don't think that could be FTP server issue (it's a ProFTPD server) as it is a well-known FTP server.
Every time a connection is made and closed, the number of threads increases by 1. I don't think garbage collection would fix that. Number of threads is consistently increasing and forcing garabage collector to run doesn't decrease that either. I think there is some leak in my code that is also causing issue #1.
Edit:
Restarting the FTP server didn't fix the problem, so there is definitely a bug in the TCPForwarder.
Some issues pointed out by #jgauffin is fixed in the below code.
Here is the full code:
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Threading;
namespace TCPForwarder
{
class Program
{
private class State
{
public int ID { get; private set; } // for debugging purposes
public Socket SourceSocket { get; private set; }
public Socket DestinationSocket { get; private set; }
public byte[] Buffer { get; private set; }
public State(int id, Socket source, Socket destination)
{
ID = id;
SourceSocket = source;
DestinationSocket = destination;
Buffer = new byte[8192];
}
}
public class TcpForwarder
{
public void Start(IPEndPoint local, IPEndPoint remote)
{
Socket MainSocket;
try
{
MainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
MainSocket.Bind(local);
MainSocket.Listen(10);
}
catch (Exception exp)
{
Console.WriteLine("Error on listening to " + local.Port + ": " + exp.Message);
return;
}
while (true)
{
// Accept a new client
var socketSrc = MainSocket.Accept();
var socketDest = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
// Connect to the endpoint
socketDest.Connect(remote);
}
catch
{
socketSrc.Shutdown(SocketShutdown.Both);
socketSrc.Close();
Console.WriteLine("Exception in connecting to remote host");
continue;
}
// Wait for data sent from client and forward it to the endpoint
StartReceive(0, socketSrc, socketDest);
// Also, wait for data sent from endpoint and forward it to the client
StartReceive(1, socketDest, socketSrc);
}
}
private static void StartReceive(int id, Socket src, Socket dest)
{
var state = new State(id, src, dest);
Console.WriteLine("{0} StartReceive: BeginReceive", id);
try
{
src.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, OnDataReceive, state);
}
catch
{
Console.WriteLine("{0} Exception in StartReceive: BeginReceive", id);
}
}
private static void OnDataReceive(IAsyncResult result)
{
State state = null;
try
{
state = (State)result.AsyncState;
Console.WriteLine("{0} OnDataReceive: EndReceive", state.ID);
var bytesRead = state.SourceSocket.EndReceive(result);
if (bytesRead > 0)
{
state.DestinationSocket.Send(state.Buffer, bytesRead, SocketFlags.None);
Console.WriteLine("{0} OnDataReceive: BeginReceive", state.ID);
state.SourceSocket.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, OnDataReceive, state);
}
else
{
Console.WriteLine("{0} OnDataReceive: Close (0 read)", state.ID);
state.SourceSocket.Shutdown(SocketShutdown.Both);
state.DestinationSocket.Shutdown(SocketShutdown.Both);
state.DestinationSocket.Close();
state.SourceSocket.Close();
}
}
catch
{
if (state!=null)
{
Console.WriteLine("{0} OnDataReceive: Close (exception)", state.ID);
state.SourceSocket.Shutdown(SocketShutdown.Both);
state.DestinationSocket.Shutdown(SocketShutdown.Both);
state.DestinationSocket.Close();
state.SourceSocket.Close();
}
}
}
}
static void Main(string[] args)
{
List<Socket> sockets = new List<Socket>();
int srcPortStart = int.Parse(args[2]);
int srcPortEnd = int.Parse(args[3]);
int destPortStart = int.Parse(args[4]);
List<Thread> threads = new List<Thread>();
for (int i = 0; i < srcPortEnd - srcPortStart + 1; i++)
{
int srcPort = srcPortStart + i;
int destPort = destPortStart + i;
TcpForwarder tcpForwarder = new TcpForwarder();
Thread t = new Thread(new ThreadStart(() => tcpForwarder.Start(
new IPEndPoint(IPAddress.Parse(args[0]), srcPort),
new IPEndPoint(IPAddress.Parse(args[1]), destPort))));
t.Start();
threads.Add(t);
}
foreach (var t in threads)
{
t.Join();
}
Console.WriteLine("All threads are closed");
}
}
}
The first problem is that the code will continue on connection failure on the destination socket (the accept loop). Use a continue; in the try/catch. There is also no guarantee that the sockets are still up when you invoke the first BeginReceive. Those calls also need to be wrapped.
Always wrap callback methods in a try/catch as your application can fail otherwise (in this case OnDataRecieve).
Fix that and start to write out the exceptions. They will surely give you a hint about what went wrong.
I'm trying to setup a tcp .net socket network with Visual Studio 2010. So far it works I can connect clients up to it but currently I have no way of defining the clients that are connected. I need like an array of clients that are connected so I can be more specific about who i streamWrite to.
This is my server code I am copying all of this from http://www.codeproject.com/Articles/511814/Multi-client-per-one-server-socket-programming-in
SERVER CODE
static TcpListener tcpListener = new TcpListener(25000);
static void Listeners()
{
Socket socketForClient = tcpListener.AcceptSocket();
if (socketForClient.Connected)
{
Console.WriteLine("Client:"+socketForClient.RemoteEndPoint+" now connected to server.");
NetworkStream networkStream = new NetworkStream(socketForClient);
System.IO.StreamWriter streamWriter =
new System.IO.StreamWriter(networkStream);
System.IO.StreamReader streamReader =
new System.IO.StreamReader(networkStream);
Console.WriteLine("type your message to be recieved by client:");
string theString2 = Console.ReadLine();
streamWriter.WriteLine(theString2);
Console.WriteLine(theString2);
streamWriter.Flush();
while (true)
{
string theString = streamReader.ReadLine();
Console.WriteLine("Message recieved by client:" + theString);
if (theString == "exit")
break;
}
streamReader.Close();
networkStream.Close();
streamWriter.Close();
}
socketForClient.Close();
Console.WriteLine("Press any key to exit from server program");
Console.ReadKey();
}
public static void Main()
{
tcpListener.Start();
Console.WriteLine("************This is Server program************");
Console.WriteLine("Hoe many clients are going to connect to this server?:");
int numberOfClientsYouNeedToConnect = int.Parse(Console.ReadLine());
for (int i = 0; i < numberOfClientsYouNeedToConnect; i++)
{
Thread newThread = new Thread(new ThreadStart(Listeners));
newThread.Start();
}
}
If you want to stick to raw TCP Sockets, then you could pass a delegate/handler etc to the thread:
for (int i = 0; i < numberOfClientsYouNeedToConnect; i++)
{
Thread newThread = new Thread(new ParameterizedThreadStart(Listeners));
newThread.Start(i);
}
Your listener then needs to take an object to match the ParametrizedThreadStart see MSDN
However, if you are developing both ends (as I commented) I'd suggest something more abstract like ASP.NET SignalR or similar for such a scenario. It adds a bit overhead, but you get Server-To-Client and vice versa communication on a conveniently abstractioned level.
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.
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