I am in desperate need of help. I have essentially created a program that (will use) encryption to send messages back and forth. The encryption part is working fine, however I am fairly new to Threads and I can not for the life of me get my Client/Server pieces of the application to line up. The chat program is direct IP connection using TCP, so each host is a client and a server. The issue I appear to be having, when I debug, is that the server thread is either not ready when the Client tries to connect to it, or if it is ready it will not relinquish the Thread so the Client can connect! I have been working on this for hours and it is very frustrating.. I hope someone can help! I've included my code below.
This is my code snippet from my MainForm, which constructs the Client and Server aspects:
private void InitializeComponent() {
server = new ServerSide("127.0.0.1",7865);
servThread = new Thread(new ThreadStart(server.begin));
client = new ClientSide("127.0.0.1",7865);
clientThread = new Thread(new ThreadStart(client.begin));
servThread.Start();
clientThread.Start();
//servThread.Join();
//clientThread.Join();
}
This is my ServerSide code:
public class ServerSide
{
String IpString;
int tcpPort;
bool goodToGo = false;
System.Net.IPAddress ipAddress = null;
public ServerSide(String ip, int tcpPort)
{
IpString = ip;
bool isValidIp = System.Net.IPAddress.TryParse(IpString, out ipAddress);
if (isValidIp == true) // check if the IP is valid, set the bool to true if so
{
goodToGo = true;
}
else
{
goodToGo = false;
}
}
public void begin()
{
try
{
IPAddress ipAd = IPAddress.Parse(IpString);
/* Initializes the Listener */
TcpListener myList = new TcpListener(ipAd, tcpPort);
Socket s = null;
/* Start Listening at the specified port */
while (true)
{
myList.Start();
if (myList.Pending())
{
s = myList.AcceptSocket();
break;
}
}
String toReceive = "";
while (true)
{
byte[] b = new byte[4096];
int k = s.Receive(b);
for (int i = 0; i < k; i++)
toReceive += Convert.ToString((Convert.ToChar(b[i])));
// ASCIIEncoding asen = new ASCIIEncoding();
var form = MainForm.ActiveForm as MainForm;
if (form != null)
{
form.messageReceived(toReceive);
}
toReceive = "";
}
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
}
}
ClientSide code:
public class ClientSide
{
private String IpString;
private int tcpPort;
private TcpClient tcpInt;
private static Stream stm;
private System.Net.IPAddress ipAddress = null;
private bool goodToGo = false;
public ClientSide(String ip, int tcpPort)
{
IpString = ip;
this.tcpPort = tcpPort;
bool isValidIp = System.Net.IPAddress.TryParse(IpString, out ipAddress);
if (isValidIp == true)
{
goodToGo = true;
}
else
{
goodToGo = false;
}
}
public void begin()
{
try
{
tcpInt = new TcpClient();
// Console.WriteLine("Connecting.....");
tcpInt.Connect(IpString, tcpPort);
// use the ipaddress as in the server program
// Console.WriteLine("Connected");
// String str = Console.ReadLine();
stm = tcpInt.GetStream();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
public void sendMessage(String str)
{
// stm = tcpInt.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
stm.Write(ba, 0, ba.Length);
/** byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
for (int i = 0; i < k; i++)
Console.Write(Convert.ToChar(bb[i]));*/
}
}
}
Once again.. what typically happens is my Client receives an error that the host actively refused the connection.. but I do not know how to time them. I am looking for how to have my server listening for TCP Connections, but still manage to go to my other thread to create the TCP Connecion to send the server (I am testing this on localhost currently).
Thanks.
In the constructor of the ServerSide class, you forgot to initialize the tcpPort member. Because you forgot, the server will try to listen to port 0 and the client will try to connect to port 7865, and it will fail.
Try adding this code to the constructor in the ServerSide class.
this.tcpPort = tcpPort;
As for the threads, you might have a problem if the client thread tries to connect before the server thread has started listening. You can use a loop to try to connect a number of times (let's say 10), with a timeout (let's say 1 second) if you don't succeed. This way, you will retry 10 times and give up after that.
Related
I'm writing app on android, which would communicate with c# server via TCP protocol. My code works fine when I use wi-fi and now I want to change it that it would work even if android client would use mobile data
Server in c# (only recive and send data):
static void Main(string[] args)
{
//setup
Program prog = new Program();//to run non-static void from static context
//main server
try
{
IPAddress ipAd = IPAddress.Parse("192.168.x.xxx");
// Initializes the Listener
TcpListener myList = new TcpListener(ipAd, 11000);
/* Start Listeneting at the specified port */
myList.Start();
//label com
com:
//accept connection
Socket s = myList.AcceptSocket();
Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);
//recive data
byte[] b = new byte[100];
int k = s.Receive(b);
char cc = ' ';
string text = null;//wil produce recived text
Console.Write("Recieved: ");
for (int i = 0; i < k - 1; i++)
{
Console.Write(Convert.ToChar(b[i]));
cc = Convert.ToChar(b[i]);
text += cc.ToString();
}
Console.WriteLine();
//analyze text
string reply = prog.analyzeText(text);
//send reply
ASCIIEncoding asen = new ASCIIEncoding();//is using to encode reply<string> to possible to send format
s.Send(asen.GetBytes(reply));//send
s.Close();
/* clean up */
goto com;
s.Close();
myList.Stop();
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.StackTrace);
Console.ReadLine();
}
}
and android client code:
private String connectSocket(String msg) {//send and receive data from server
try {
InetAddress serverAddr = InetAddress.getByName("192.168.x.xxx");
Socket socket = new Socket(serverAddr, 11000);
//define PrintWriter
PrintWriter out = null;
try {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
final BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out.println(msg);
String text = "";
String finalText = "";
while ((text = in.readLine()) != null) {
finalText += text;
}
socket.close();
return finalText;
} catch (Exception e) {
Toast.makeText(getApplicationContext(),"Something went wrong.\nTry again in few minutes",Toast.LENGTH_SHORT).show();
return "exception";
} finally {
socket.close();
}
} catch (UnknownHostException e) {
return "UnknownHostException";
} catch (IOException e) {
return "IOException";
}
}
PS. sorry for my english, but I started learning it only 1 year ago
There's no code changes needed. You might need to set up your network correctly so there's no firewalls in the way around your test server (and that may include talking to your ISP, if they have a firewall preventing incoming connections). But standard socket communication works over wifi or mobile.
I've got a product plugged directly into the ethernet port of my computer, sending multicast packets to 224.224.10.10 and UDP port 24588. I've set up my UDPclient in the code below, and I feel like I have it set up correctly, but I still don't receive any packets. I always catch an exception saying that I timed out waiting for a response. Any thoughts or glaring mistakes?
I looked at a lot of questions before posting this, but I couldn't get a resolution, and I couldn't find anyone who had the same type of setup that I have.
public class ReceiverClass
{
private UdpClient m_UDPClient = null;
private Thread m_UDPReceiverThread = null;
private bool m_ContinueReceiving = false;
private readonly object m_sync = new object();
private const int UDP_PORT = 24588;
public ReceiverClass()
{
m_ContinueReceiving = true;
m_UDPClient = new UdpClient(UDP_PORT);
m_UDPClient.Client.ReceiveTimeout = 20000;
m_UDPReceiverThread = new Thread(ReceiveData) { IsBackground = true };
m_UDPReceiverThread.Start();
}
private void ReceiveData()
{
bool Continue;
byte[] ReceiveBuffer;
IPEndPoint defaultIP = new IPEndPoint(IPAddress.Any, 0);
m_UDPClient.JoinMulticastGroup(IPAddress.Parse("224.224.10.10"));
m_UDPClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
lock (m_sync)
{
Continue = m_ContinueReceiving;
}
while (Continue)
{
try
{
ReceiveBuffer = m_UDPClient.Receive(ref defaultIP);
if (null != ReceiveBuffer)
{
// Do stuff with received...
}
}
catch (Exception e)
{
// ooo eee kill stream
Dispose(false);
return;
}
finally
{
lock (m_sync)
{
Continue = m_ContinueReceiving;
}
}
}
}
}
I can't see anything immediately wrong with your code so I don't have a proper answer for you. However, here's a piece of code I'm using to get UDP broadcast messages. Hopefully it will work for you, or give you some new ideas:
class UdpHandler {
public UdpHandler(int portNo) {
Thread t = new Thread(ListenThread);
t.IsBackground = true;
t.Start(portNo);
}
public void ListenThread(object portNo) {
UdpClient client = new UdpClient { ExclusiveAddressUse = false };
IPEndPoint localEp = new IPEndPoint(IPAddress.Any, (int)port);
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.ExclusiveAddressUse = false;
client.Client.Bind(localEp);
while (true) {
byte[] data = client.Receive(ref localEp);
DataReceived(data);
}
}
private void DataReceived(byte[] rawData) {
// Handle the received data
}
}
What I ended up doing was going to the Sockets class and looking at the raw packets and picking out what I needed. I bind the socket to my lan interface, and sniff stuff out. I had to run it as an administrator in order to get it to work, but thats fine. I went this route because I could see the packets in wireshark, but they weren't getting to my udpclient. This ended up being the fastest way to get what I wanted.
Socket ReceiveSocket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
EndPoint DefaultIPEndpoint = new IPEndPoint(IPAddress.Parse("10.0.2.0"), 0);
ReceiveSocket.ReceiveTimeout = 5000;
ReceiveSocket.Bind(DefaultIPEndpoint);
ReceiveSocket.IOControl(IOControlCode.ReceiveAll, new byte[4] { 1, 0, 0, 0 }, null);
while (true)
{
byte[] ReceiveBuffer = new byte[512];
int ByteCount = 0;
ByteCount = ReceiveSocket.ReceiveFrom(ReceiveBuffer, ref DefaultIPEndpoint);
// Handle packets ...
}
I've got a generic TCP Client and TCP Listener setup on my main laptop and my other laptop. The client and listener are their own separate programs, so I've had a client and server running on both laptops to try and get a simple instant messenger going.
The client and server will happily communicate with each other if both programs are executed on the same laptop. This is true for both my main and other laptop.
My main laptop's client will happily send messages to my other laptop, and the other laptop will gracefully receive messages from my main laptop.
However, when my other laptop's client sends a message to my main laptop's server it gets a timeout-related, communication-failed type of error. It just doesn't send the message.
Error message (caught by try-catch); "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond {my IP:port number}."
I'm getting the IP and port numbers correct, so rule that out.
There's no firewall business because the other laptop doesn't care at all about receiving messages from my main laptop.
I've also tried random port numbers and made sure that the client on my main laptop is connecting over the same port number that my other laptop's sever is listening on (or accepting messages from).
So why isn't my other laptop successfully sending messages to my main laptop?
The client asks for the user to enter an IP and then a port number. It then waits for the user to enter a message, then connects and sends that message to the IP via the given port number.
The server asks the user to enter a port number and prints messages received through that port.
Here's the code for the client program;
static void Main(string[] args)
{
string IP = localIPAddress();
Console.WriteLine("Your IP: " + IP); //provides IP number
Console.Write("Enter IP to connect to: ");
string connectToIP = Console.ReadLine();
if (connectToIP == "self")
{
connectToIP = localIPAddress();
// if I want to test both on the same computer
}
Console.WriteLine("\nEnter port number: ");
int portNo = int.Parse(Console.ReadLine());
while (true)
{
string message = Console.ReadLine();
try
{
// connection doesn't begin until ReadLine is done
request(connectToIP, portNo, message);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
public static string localIPAddress()
{
IPHostEntry host;
string localIP = "?";
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
localIP = ip.ToString();
}
}
return localIP;
}
static void request(string address, int port, string message)
{
TcpClient client = new TcpClient();
client.SendTimeout = 1000;
client.ReceiveTimeout = 1000;
try
{
client.Connect(address, port);
StreamWriter sw = new StreamWriter(client.GetStream());
sw.WriteLine(message);
sw.Flush();
sw.Close();
}
catch (Exception a)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(a.Message.ToString());
Console.ResetColor();
}
}
Here's the code for the server;
static void Main(string[] args)
{
Console.WriteLine("Your IP: " + localIPAddress());
Console.Write("Enter port number you're receiving from: ");
int portNo = int.Parse(Console.ReadLine());
TcpListener listener = new TcpListener(IPAddress.Any, portNo);
Socket connection;
NetworkStream socketStream;
listener.Start();
while (true)
{
connection = listener.AcceptSocket();
connection.SendTimeout = 1000;
connection.ReceiveTimeout = 1000;
socketStream = new NetworkStream(connection);
try
{
respond(socketStream);
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
socketStream.Close();
connection.Close();
}
}
}
public static string localIPAddress()
{
IPHostEntry host;
string localIP = "?";
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
localIP = ip.ToString();
}
}
return localIP;
}
static void respond(NetworkStream strm)
{
List<string> sentIn = new List<string>();
StreamReader sr = new StreamReader(strm);
while (sr.Peek() != -1)
sentIn.Add(sr.ReadLine());
sr.Close();
foreach (string s in sentIn)
{
Console.WriteLine(s);
}
}
Is there a problem with my code? There have been no Firewall-related messages when either laptop uses these programs.
It might be the sw.Flush() for the client, because that used to cause the sending process to freeze.
Thanks in advance. Once I get this problem sorted, I can start wondering how this can be used to make a multiplayer XNA game.
You might want to try making the timeouts a little longer (or remove them all together; they caused problems for me). Also, it's really a good idea to create a thread to receive messages while you handle the sending on the main thread.
Some notes:
You can use "loopback" or "127.0.0.1" if you'd like to connect to your local IP
if (connectToIP == "self")
{
connectToIP = localIPAddress();
// if I want to test both on the same computer
}
You really shouldn't connect, send a single message, and then disconnect, only to connect again.
Try something like this for the client:
using System.Threading;
static void Main(string[] args)
{
TcpClient client = new TcpClient();
Console.Write("IP: ");
string ip = Console.ReadLine();
Console.Write("Port: ");
int port = int.Parse(Console.ReadLine());
try
{
client.Connect(ip, port);
StreamWriter sw = new StreamWriter(client.GetStream());
sw.AutoFlush = true;
StreamReader sr = new StreamReader(client.GetStream());
Thread readThread = new Thread(() => readSocket(sr));
readThread.Start(); //Run readSocket() at the same time
string message = "";
while (message != "exit")
{
message = Console.ReadLine();
sw.WriteLine(message);
}
client.Close();
return;
}
catch (Exception e) { Console.WriteLine(e.ToString()); }
}
static void readSocket(StreamReader sr)
{
try
{
string message = "";
while ((message = sr.ReadLine()) != null)
{
Console.WriteLine(message);
}
}
catch (System.IO.IOException) { /*when we force close, this goes off, so ignore it*/ }
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
Here's an example of the Server:
static void Main(string[] args)
{
Console.Write("Port: ");
int port = int.Parse(Console.ReadLine());
TcpListener server = new TcpListener(IPAddress.Any, port);
try
{
server.Start();
TcpClient client = server.AcceptTcpClient();
StreamWriter sw = new StreamWriter(client.GetStream());
sw.AutoFlush = true;
StreamReader sr = new StreamReader(client.GetStream());
Thread readThread = new Thread(() => readSocket(sr));
readThread.Start();
string message = "";
while (message != "exit")
{
message = Console.ReadLine();
sw.WriteLine(message);
}
client.Close();
return;
}
catch (Exception e) { Console.WriteLine(e.ToString()); }
}
static void readSocket(StreamReader sr)
{
try
{
string message = "";
while ((message = sr.ReadLine()) != null)
{
Console.WriteLine(message);
}
}
catch (System.IO.IOException) { /*when we force close, this goes off, so ignore it*/ }
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
Here is the code for an Async server that forwards messages to all connected clients (If you were worried about not being able to share a port).
I'm trying to keep these examples simple, but it's probably a good idea to add more exception handling to all of them.
class Server
{
private int port;
private Socket serverSocket;
private List<StateObject> clientList;
private const int DEFAULT_PORT = 1338;
public Server()
{
this.port = 1338; //default port
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientList = new List<StateObject>();
}
public Server(int port)
{
this.port = port;
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientList = new List<StateObject>();
}
public void startListening(int port = DEFAULT_PORT)
{
this.port = port;
serverSocket.Bind(new IPEndPoint(IPAddress.Any, this.port));
serverSocket.Listen(1);
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
private void AcceptCallback(IAsyncResult AR)
{
try
{
StateObject state = new StateObject();
state.workSocket = serverSocket.EndAccept(AR);
//Console.WriteLine("Client Connected");
clientList.Add(state);
state.workSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
catch { }
}
private void ReceiveCallback(IAsyncResult AR)
{
StateObject state = (StateObject)AR.AsyncState;
Socket s = state.workSocket;
try
{
int received = s.EndReceive(AR);
if (received == 0)
return;
if (received > 0)
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, received));
string content = state.sb.ToString();
if (content.IndexOf(Environment.NewLine) > -1)
{
//Console.WriteLine(content);
foreach (StateObject others in clientList)
if (others != state)
others.workSocket.Send(Encoding.ASCII.GetBytes(content.ToCharArray()));
state.sb.Clear();
}
Array.Clear(state.buffer, 0, StateObject.BufferSize);
s.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
catch (Exception huh) {
s.Close();
s.Dispose();
//Console.WriteLine("Client Disconnected");
clientList.Remove(state);
return;
}
}
class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}
}
I want to send a message from a C# application to the Android emulator or device over TCP. I have searched on Google and got the maximum results for Android client and C# server but not what I want to acheive.
Here is what I have tried; maybe I am going about it the wrong way but what I want is to send a message over TCP to an Android device.
Server Code to send a message:
private static int port = 4444;
private static TcpListener listener;
private static Thread thread;
private static int clientId = 0;
listener = new TcpListener(new IPAddress(new byte[] { 127, 0, 0, 1 }), port);
thread = new Thread(new ThreadStart(Listen));
thread.Start();
private static void Listen()
{
listener.Start();
MessageBox.Show("Listening on: " + port.ToString());
while (true)
{
MessageBox.Show("Waiting for connection....");
MessageBox.Show("Client No: " + clientId);
TcpClient client = listener.AcceptTcpClient();
Thread listenThread = new Thread(new ParameterizedThreadStart(ListenThread));
listenThread.Start(client);
}
}
private static void ListenThread(Object client)
{
NetworkStream netstream = ((TcpClient)client).GetStream();
MessageBox.Show("Request made");
clientId = clientId + 1;
// String message = "Hello world";
byte[] resMessage = Encoding.ASCII.GetBytes(clientId.ToString());
netstream.Write(resMessage, 0, resMessage.Length);
netstream.Close();
}
Client Code
private TextView textDisplay;
Socket socket;
private static final int TCP_SERVER_PORT = 4444;
ServerSocket ss = null;
try {
ss = new ServerSocket(TCP_SERVER_PORT);
//ss.setSoTimeout(10000);
//accept connections
Socket s = ss.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//receive a message
String incomingMsg = in.readLine() + System.getProperty("line.separator");
Log.d("TcpServer", "received: " + incomingMsg);
textDisplay.append("received: " + incomingMsg);
//send a message
String outgoingMsg = "goodbye from port " + TCP_SERVER_PORT + System.getProperty("line.separator");
out.write(outgoingMsg);
out.flush();
Log.d("TcpServer", "sent: " + outgoingMsg);
textDisplay.append("sent: " + outgoingMsg);
//SystemClock.sleep(5000);
s.close();
} catch (InterruptedIOException e) {
//if timeout occurs
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
Log.d("Error",e.toString());
}
}
}
The problem lies in your Client code.
A socket is opened between two parties, one that plays the role of the listener / server that does bind->listen->accept and a client that connect
In your code there are two problems:
Your client should connect and not accept
Both your client and your server will try to read from the socket and write afterwards. There would be no problem if your read and write operations from the socket were on different threads.In your case this will result in a deadlock.
If you want both operations to be done on the same thread , sequentially then your client and server should perform the read and write in opposite order :
Client : read -> write
Server: write-> read
hey all,
I have made a socket server in C# for a flash game that I am developing, I got the code from somewhere and I am a beginner in c# and .net development . It works fine in practice when connections are made and the server functions correctly. Get 2 concurrent connections at the same time and we have a problem.
here is the basic aspects of the socket server below: (alot taken out for obvious reasons)
how can I alter this so that it can handle concurrent connections? Should I be threading each response?
Thanks
class TcpSock
{
int tcpIndx = 0;
int tcpByte = 0;
byte[] tcpRecv = new byte[1024];
////////////////////////////////////////
public Socket tcpSock;
////////////////////////////////////////
public int Recv(ref string tcpRead)
{
tcpByte = tcpSock.Available;
if (tcpByte > tcpRecv.Length - tcpIndx)
tcpByte = tcpRecv.Length - tcpIndx;
tcpByte = tcpSock.Receive(tcpRecv, tcpIndx, tcpByte,
SocketFlags.Partial);
tcpRead = Encoding.ASCII.GetString
(tcpRecv, tcpIndx, tcpByte);
tcpIndx += tcpByte;
return tcpRead.Length;
}
public int RecvLn(ref string tcpRead)
{
tcpRead = Encoding.ASCII.GetString
(tcpRecv, 0, tcpIndx);
tcpIndx = 0;
return tcpRead.Length;
}
public int Send(string tcpWrite)
{
return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite));
}
public int SendLn(string tcpWrite)
{
return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite + "\r\n"));
}
}
[STAThread]
static void Main()
{
Thread Server1 = new Thread(RunServer);
Server1.Start();
}
static void RunServer()
{
///class IPHostEntry : Stores information about the Host and is required
///for IPEndPoint.
///class IPEndPoint : Stores information about the Host IP Address and
///the Port number.
///class TcpSock : Invokes the constructor and creates an instance.
///class ArrayList : Stores a dynamic array of Client TcpSock objects.
IPHostEntry Iphe = Dns.Resolve(Dns.GetHostName());
IPEndPoint Ipep = new IPEndPoint(Iphe.AddressList[0], 4444);
Socket Server = new Socket(Ipep.Address.AddressFamily,SocketType.Stream, ProtocolType.Tcp);
///Initialize
///Capacity : Maximux number of clients able to connect.
///Blocking : Determines if the Server TcpSock will stop code execution
///to receive data from the Client TcpSock.
///Bind : Binds the Server TcpSock to the Host IP Address and the Port Number.
///Listen : Begin listening to the Port; it is now ready to accept connections.
ArrayList Client = new ArrayList();
string[,] Users = new string[1000,9];
string rln = null;
string[] Data;
Client.Capacity = 1000;
Server.Blocking = false;
Server.Bind(Ipep);
Server.Listen(32);
Console.WriteLine("Server 1 {0}: listening to port {1}", Dns.GetHostName(), Ipep.Port);
////////////////////////////////////////////////////////////////////////////////////////////
///Main loop
///1. Poll the Server TcpSock; if true then accept the new connection.
///2. Poll the Client TcpSock; if true then receive data from Clients.
while (true)
{
//Accept - new connection
#region new connection
if (Server.Poll(0, SelectMode.SelectRead))
{
int i = Client.Add(new TcpSock());
((TcpSock)Client[i]).tcpSock = Server.Accept();
Console.WriteLine("Client " + i + " connected.");
Users[i, 0] = i.ToString();
}
#endregion
for (int i = 0; i < Client.Count; i++)
{
//check for incoming data
if (((TcpSock)Client[i]).tcpSock.Poll(0, SelectMode.SelectRead))
{
//receive incoming data
if (((TcpSock)Client[i]).Recv(ref rln) > 0)
{
Console.WriteLine(rln.ToString());
Data = rln.Split('|');
// 1) initial connection
#region InitialConnection
if (Data[0] == "0000")
{
}
}
}
}
}
}
You will need to not use synchronous functions but asynchrounus functions like Socket.BeginReceive
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
public static partial class TcpServer
{
public static void Main()
{
// Setup listener on "localhost" port 12000
IPAddress ipAddr = Dns.GetHostEntry("localhost").AddressList[0];
TcpListener server = new TcpListener(ipAddr, 12000);
server.Start(); // Network driver can now allow incoming requests
// Accept up to 1 client per CPU simultaneously
Int32 numConcurrentClients = Environment.ProcessorCount;
for (Int32 n = 0; n
private static Byte[] ProcessData(Byte[] inputData)
{
String inputString = Encoding.UTF8.GetString(inputData, 1, inputData[0]);
String outputString = inputString.ToUpperInvariant();
Console.WriteLine("Input={0}", inputString);
Console.WriteLine(" Output={0}", outputString);
Console.WriteLine();
Byte[] outputStringBytes = Encoding.UTF8.GetBytes(outputString);
Byte[] outputData = new Byte[1 + outputStringBytes.Length];
outputData[0] = (Byte)outputStringBytes.Length;
Array.Copy(outputStringBytes, 0, outputData, 1, outputStringBytes.Length);
return outputData;
}
}
public static partial class TcpServer
{
private sealed class ClientConnectionApm
{
private TcpListener m_server;
private TcpClient m_client;
private Stream m_stream;
private Byte[] m_inputData = new Byte[1];
private Byte m_bytesReadSoFar = 0;
public ClientConnectionApm(TcpListener server)
{
m_server = server;
m_server.BeginAcceptTcpClient(AcceptCompleted, null);
}
private void AcceptCompleted(IAsyncResult ar)
{
// Connect to this client
m_client = m_server.EndAcceptTcpClient(ar);
// Accept another client
new ClientConnectionApm(m_server);
// Start processing this client
m_stream = m_client.GetStream();
// Read 1 byte from client which contains length of additional data
m_stream.BeginRead(m_inputData, 0, 1, ReadLengthCompleted, null);
}
private void ReadLengthCompleted(IAsyncResult result)
{
// If client closed connection; abandon this client request
if (m_stream.EndRead(result) == 0) { m_client.Close(); return; }
// Start to read 'length' bytes of data from client
Int32 dataLength = m_inputData[0];
Array.Resize(ref m_inputData, 1 + dataLength);
m_stream.BeginRead(m_inputData, 1, dataLength, ReadDataCompleted, null);
}
private void ReadDataCompleted(IAsyncResult ar)
{
// Get number of bytes read from client
Int32 numBytesReadThisTime = m_stream.EndRead(ar);
// If client closed connection; abandon this client request
if (numBytesReadThisTime == 0) { m_client.Close(); return; }
// Continue to read bytes from client until all bytes are in
m_bytesReadSoFar += (Byte)numBytesReadThisTime;
if (m_bytesReadSoFar
private void WriteDataCompleted(IAsyncResult ar)
{
// After result is written to client, close the connection
m_stream.EndWrite(ar);
m_client.Close();
}
}
}
First of all: Stop using non-blocking sockets. In .NET you should either stick to the synchronous methods Receive/Send or asynchronous methods BeginReceive/BeginSend.
You should only stick with sync methods if you will have only a handful of clients. Then launch each new client in a new thread. This is the easiest option to get everthing running.
Simply do like this:
public void AcceptClients()
{
TcpListener listener = new TcpListener(IPAddress.Any, 5566);
listener.Start();
while (_serverRunning)
{
var socket = listener.AcceptSocket();
new Thread(ClientFunc).Start(socket);
}
}
public void ClientFun(object state)
{
var clientSocket = (Socket)state;
var buffer = new byte[65535];
while (_serverRunning)
{
//blocking read.
clientSocket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
//check packet.
// handle packet
// send respons.
clientSocket.Send(alalalal);
}
}
You should refactor the methods so that they follow SRP. The code is just a small guide to get you going.