Async socket server with multiple clients - c#

i have a problem i am unable to resolve as my c# knowledge is not very good.
I found some code on the internet and modified it according to my needs.
My problem is that when i send messages to clients only one receives the message, then the next message is received by another client and so on.
I want to send same message to all connected clients without losing any data.
Server
using System;
using System.Net.Sockets;
using System.Threading;
public class AsynchIOServer
{
static TcpListener tcpListener = new TcpListener(10);
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);
////here we send message to client
while (true){
Console.WriteLine("type your message to be recieved by client:");
string theString = Console.ReadLine();
streamWriter.WriteLine(theString);
////Console.WriteLine(theString);
streamWriter.Flush();
}
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 tcpListener = new TcpListener(10);
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();
}
}
}
Client:
using System;
using System.Net.Sockets;
using System.Threading;
public class Client
{
static public void Main(string[] Args)
{
TcpClient socketForServer;
try
{
socketForServer = new TcpClient("localHost", 10);
}
catch
{
Console.WriteLine(
"Failed to connect to server at {0}:999", "localhost");
return;
}
NetworkStream networkStream = socketForServer.GetStream();
System.IO.StreamReader streamReader =
new System.IO.StreamReader(networkStream);
System.IO.StreamWriter streamWriter =
new System.IO.StreamWriter(networkStream);
Console.WriteLine("*******This is client program who is connected to localhost on port No:10*****");
try
{
string outputString;
// read the data from the host and display it
{
while (true)
{
outputString = streamReader.ReadLine();
Console.WriteLine("Message Recieved by server:" + outputString);
streamWriter.Flush();
}
}
}
catch
{
Console.WriteLine("Exception reading from Server");
}
// tidy up
networkStream.Close();
Console.WriteLine("Press any key to exit from client program");
Console.ReadKey();
}
private static string GetData()
{
//Ack from sql server
return "ack";
}
}
Thank you

simple working multi-threaded server:
static void Process(Socket client) {
Console.WriteLine("Incoming connection from " + client.RemoteEndPoint);
const int maxMessageSize = 1024;
byte[] response;
int received;
while (true) {
// Send message to the client:
Console.Write("Server: ");
client.Send(Encoding.ASCII.GetBytes(Console.ReadLine()));
Console.WriteLine();
// Receive message from the server:
response = new byte[maxMessageSize];
received = client.Receive(response);
if (received == 0) {
Console.WriteLine("Client closed connection!");
return;
}
List<byte> respBytesList = new List<byte>(response);
respBytesList.RemoveRange(received, maxMessageSize - received); // truncate zero end
Console.WriteLine("Client (" + client.RemoteEndPoint + "+: " + Encoding.ASCII.GetString(respBytesList.ToArray()));
}
}
static void Main(string[] args) {
int backlog = -1, port = 2222;
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.ReceiveTimeout = -1;
// Start listening.
try {
server.Bind(new IPEndPoint(IPAddress.Any, port));
server.Listen(backlog);
}
catch (Exception) {
Console.WriteLine("Listening failed!");
Console.ReadKey();
return;
}
Console.WriteLine("Start listening...");
while(true) {
Socket client = server.Accept();
new System.Threading.Thread(() => {
try { Process(client); } catch (Exception ex) { Console.WriteLine("Client connection processing error: " + ex.Message); }
}).Start();
}
//Console.WriteLine("Press any key for exit...");
//Console.ReadKey();
}
And client:
static void WorkWithServer(Socket server) {
const int maxMessageSize = 1024;
byte[] response;
int received;
while(true) {
try {
// Receive message from the server:
response = new byte[maxMessageSize];
received = server.Receive(response);
if (received == 0) {
Console.WriteLine("Server closed connection.");
return;
}
List<byte> respBytesList = new List<byte>(response);
respBytesList.RemoveRange(received, maxMessageSize - received); // truncate zero end
Console.WriteLine("Server: " + Encoding.ASCII.GetString(respBytesList.ToArray()));
// Send message to the server:
Console.Write("You: ");
server.Send(Encoding.ASCII.GetBytes(Console.ReadLine()));
Console.WriteLine();
}
catch (Exception ex) {
Console.WriteLine("Error: " + ex.Message);
return;
}
}
}
static void Main(string[] args) {
IPEndPoint serverEp = new IPEndPoint(IPAddress.Parse("192.168.1.2"), 2222);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.ReceiveTimeout = -1;
// Connect to the server.
try { server.Connect(serverEp); }
catch (Exception) {
Console.WriteLine("Establish connection with server (" + serverEp + ") failed!");
Console.ReadKey();
return;
}
Console.WriteLine("Connection with server (" + serverEp + ") established!");
WorkWithServer(server);
Console.WriteLine("Press any key for exit...");
Console.ReadKey();
}
Edit as you need.

Your code is wrong.
First of all I'll give you some insight of how it's wrong and why it's not working the way you want.
You're creating n number of threads, and making them ALL wait for a connection. What if you exhaust the number of threads? What if any of them exits unexpectedly?
You are also sending the data wrong. By using Console.ReadLine you aren't passing the data through multiple threads and reading the line in each one, instead, the first one that calls Console.ReadLine will be the one that's going to receive it. This means you'll only be sending to only one Socket.
It's not ideal how you're managing this. There are dozens if not hundreds of multithreaded socket server/client available online, and I'd invite you to research a little bit more. But first I'd like you to research more about Thread/Task in C#.

Related

C# Sockets (TCP & UDP)

I'll cut to the point, I've been stuck on this for a few hours now. Tons of Google and tons of research but not straight answer as of yet.
I have a client and a server coded for TCP which functions perfectly fine, however, I want the client to also be able to use UDP with the server for none-important packets such as player location.
As of right now, this is my connect code for connected clients.
public void ConnectToServer(){
tcp_client = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
tcp_client.Connect(server_ip, server_port);
tcp_stream = new NetworkStream(this.tcp_client);
this.udp_client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
this.udp_client.BeginConnect(IPAddress.Parse(server_ip), server_port,new AsyncCallback(udp_connected), null);
}
Now the client isn't what I've had issues with for when I use udp.Send(byteArray) it appears to be sending as it's not throwing any exceptions but the server itself isn't responding to any data received.
Please Note this is NOT 100% copy/pasted code. Alter to show just what's being an issue.
private Socket c;
private UdpClient udp;
private isRunning = true;
public Client(Socket c){
// This was accepted from TcpListener on Main Server Thread.
this.c = c;
this.networkStream = new NetworkStream(this.c);
udp = new UdpClient();
udp.Connect((IPEndPoint)c.RemoteEndPoint);
// Then starts 2 thread for listening, 1 for TCP and 1 for UDP.
}
private void handleUDPTraffic(){
IPEndPoint groupEP = (IPEndPoint)c.RemoteEndPoint;
while (isRunning){
try{
byte[] udp_received = udp.Receive(ref groupEP);
Console.WriteLine("Received UDP Packet Data: " + udp_received.Length);
}catch{
log.ERROR("UDP", "Couldn't Receive Data...");
}
}
}
You can use both TCP and UDP on the same port. See also:
Can TCP and UDP sockets use the same port?
The sample below demonstrates that, you can simultaneously send and receive UDP and TCP messages.
Maybe, your UdpClient creation to listen for incoming datagrams is the problem. I recommend to create it once like your TcpListener.
The servers:
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 TCPUDPServer
{
class Program
{
static void Main(string[] args)
{
TcpListener tcpServer = null;
UdpClient udpServer = null;
int port = 59567;
Console.WriteLine(string.Format("Starting TCP and UDP servers on port {0}...", port));
try
{
udpServer = new UdpClient(port);
tcpServer = new TcpListener(IPAddress.Any, port);
var udpThread = new Thread(new ParameterizedThreadStart(UDPServerProc));
udpThread.IsBackground = true;
udpThread.Name = "UDP server thread";
udpThread.Start(udpServer);
var tcpThread = new Thread(new ParameterizedThreadStart(TCPServerProc));
tcpThread.IsBackground = true;
tcpThread.Name = "TCP server thread";
tcpThread.Start(tcpServer);
Console.WriteLine("Press <ENTER> to stop the servers.");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("Main exception: " + ex);
}
finally
{
if (udpServer != null)
udpServer.Close();
if (tcpServer != null)
tcpServer.Stop();
}
Console.WriteLine("Press <ENTER> to exit.");
Console.ReadLine();
}
private static void UDPServerProc(object arg)
{
Console.WriteLine("UDP server thread started");
try
{
UdpClient server = (UdpClient)arg;
IPEndPoint remoteEP;
byte[] buffer;
for(;;)
{
remoteEP = null;
buffer = server.Receive(ref remoteEP);
if (buffer != null && buffer.Length > 0)
{
Console.WriteLine("UDP: " + Encoding.ASCII.GetString(buffer));
}
}
}
catch (SocketException ex)
{
if(ex.ErrorCode != 10004) // unexpected
Console.WriteLine("UDPServerProc exception: " + ex);
}
catch (Exception ex)
{
Console.WriteLine("UDPServerProc exception: " + ex);
}
Console.WriteLine("UDP server thread finished");
}
private static void TCPServerProc(object arg)
{
Console.WriteLine("TCP server thread started");
try
{
TcpListener server = (TcpListener)arg;
byte[] buffer = new byte[2048];
int count;
server.Start();
for(;;)
{
TcpClient client = server.AcceptTcpClient();
using (var stream = client.GetStream())
{
while ((count = stream.Read(buffer, 0, buffer.Length)) != 0)
{
Console.WriteLine("TCP: " + Encoding.ASCII.GetString(buffer, 0, count));
}
}
client.Close();
}
}
catch (SocketException ex)
{
if (ex.ErrorCode != 10004) // unexpected
Console.WriteLine("TCPServerProc exception: " + ex);
}
catch (Exception ex)
{
Console.WriteLine("TCPServerProc exception: " + ex);
}
Console.WriteLine("TCP server thread finished");
}
}
}
The clients:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace TCPUDPClient
{
class Program
{
static void Main(string[] args)
{
UdpClient udpClient = null;
TcpClient tcpClient = null;
NetworkStream tcpStream = null;
int port = 59567;
ConsoleKeyInfo key;
bool run = true;
byte[] buffer;
Console.WriteLine(string.Format("Starting TCP and UDP clients on port {0}...", port));
try
{
udpClient = new UdpClient();
udpClient.Connect(IPAddress.Loopback, port);
tcpClient = new TcpClient();
tcpClient.Connect(IPAddress.Loopback, port);
while(run)
{
Console.WriteLine("Press 'T' for TCP sending, 'U' for UDP sending or 'X' to exit.");
key = Console.ReadKey(true);
switch (key.Key)
{
case ConsoleKey.X:
run = false;
break;
case ConsoleKey.U:
buffer = Encoding.ASCII.GetBytes(DateTime.Now.ToString("HH:mm:ss.fff"));
udpClient.Send(buffer, buffer.Length);
break;
case ConsoleKey.T:
buffer = Encoding.ASCII.GetBytes(DateTime.Now.ToString("HH:mm:ss.fff"));
if (tcpStream == null)
tcpStream = tcpClient.GetStream();
tcpStream.Write(buffer, 0, buffer.Length);
break;
}
}
}
catch (Exception ex)
{
Console.WriteLine("Main exception: " + ex);
}
finally
{
if(udpClient != null)
udpClient.Close();
if(tcpStream != null)
tcpStream.Close();
if(tcpClient != null)
tcpClient.Close();
}
Console.WriteLine("Press <ENTER> to exit.");
Console.ReadLine();
}
}
}

C# server and client not working

I have been making a C# server and client for a game. I have used many resources to try to create something successful. So far, the client can send stuff to the server and the server can receive them, but I want to be able to send stuff to the client. Also, I don't know what happened, but my server code suddenly stopped printing to console or something. I am new at this and any help is needed. I think I programmed both client and server to be able to send and receive, but something isn't right...
Note: I am using a cmd compiler running an old version of the .NET (but the code still compiles), any help on getting visual studio working to build/compile the code would also be nice :)
Client-side:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
class Program
{
static Boolean done = false;
static void Main(string[] args)
{
Boolean exception_thrown = false;
Socket sending_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
IPAddress send_to_address = IPAddress.Parse("ip-goes-here");
IPEndPoint sending_end_point = new IPEndPoint(send_to_address, 27020);
Console.WriteLine("Enter text to broadcast via UDP.");
Console.WriteLine("Enter a blank line to exit the program.");
Thread listenerT = new Thread(new ThreadStart(Program.listener));
listenerT.Start();
while (!done)
{
Console.WriteLine("Enter text to send, blank line to quit");
string text_to_send = Console.ReadLine();
if (text_to_send.Length == 0)
{
done = true;
listenerT.Abort();
}
else
{
byte[] send_buffer = Encoding.ASCII.GetBytes(text_to_send);
Console.WriteLine("sending to address: {0} port: {1}",
sending_end_point.Address,
sending_end_point.Port);
try
{
sending_socket.SendTo(send_buffer, sending_end_point);
}
catch (Exception send_exception)
{
exception_thrown = true;
Console.WriteLine(" Exception {0}", send_exception.Message);
}
if (exception_thrown == false)
{
Console.WriteLine("Message has been sent to the broadcast address");
}
else
{
exception_thrown = false;
Console.WriteLine("The exception indicates the message was not sent.");
}
}
}
}
static void listener()
{
int listenPort = 27020;
UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
string received_data;
byte[] receive_byte_array;
try
{
while (!done)
{
Console.WriteLine("Waiting for broadcast");
receive_byte_array = listener.Receive(ref groupEP);
Console.WriteLine("Received a broadcast from {0}", groupEP.ToString());
received_data = Encoding.ASCII.GetString(receive_byte_array, 0, receive_byte_array.Length);
Console.WriteLine("data follows \n{0}\n\n", received_data);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
Server side:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
public class UDPListener
{
private const int listenPort = 27020;
//static Boolean done = false;
static IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
static UdpClient udpServer = new UdpClient(27020);
static IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 27020);
static byte[] data = udpServer.Receive(ref remoteEP); // listen on port 11000
static IPAddress send_to_address = IPAddress.Parse("10.240.0.1");
static IPEndPoint sending_end_point = new IPEndPoint(send_to_address, 27020);
public static void Main()
{
Console.WriteLine("Begin listening sequence");
while (true)
{
data = udpServer.Receive(ref groupEP);
Console.WriteLine("Received a broadcast from {0}", groupEP.ToString());
send_to_address = IPAddress.Parse(groupEP.ToString());
Thread listenerT = new Thread(new ThreadStart(UDPListener.sender));
listenerT.Start();
String received_data = Encoding.ASCII.GetString(data, 0, data.Length);
Console.WriteLine(received_data);
}
}
static void sender()
{
while (true)
{
Console.WriteLine("Enter text to send, blank line to quit");
string text_to_send = Console.ReadLine();
if (text_to_send.Length == 0)
{
//done = true;
}
else
{
byte[] send_buffer = Encoding.ASCII.GetBytes(text_to_send);
Console.WriteLine("sending to address: {0} port: {1}",
sending_end_point.Address,
sending_end_point.Port);
udpServer.Send(send_buffer, 0, remoteEP); // reply back
}
}
}
}
Nevermind, a friend of mine figured it out. You can find the final code in a github repo called something like flaming leaf server

C# TCP Chat-Server: Connection only works one way

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();
}
}

Android and c# tcp communication

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

Server remains hang when sending

I'm writting a client(Android) - server(c#) application. I get the code from here:
How to make client on Android listen to server on C#?
Everythings is working fine, when i just send message from the client to server, and from server to client (closing the socket on server side). Now, what i want is : send message to server, receive message from server, then send again a message to server. The server hangs at sending the message. If i close the socket on server side after sending, it gives a dispose error, and i can's send the data from the server.
My server code is:
/*************************************SERVER*****************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace SERVER2
{
class Program
{
public static void Main()
{
try
{
IPAddress ipAd = IPAddress.Parse("192.168.2.102");
TcpListener myList = new TcpListener(ipAd, 18001);
myList.Start();
Console.WriteLine("The server is running at port 18001...");
Console.WriteLine("The local End point is :" +
myList.LocalEndpoint);
Console.WriteLine("Waiting for a connection.....");
m:
Socket s = myList.AcceptSocket();
Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);
byte[] b = new byte[100];
int k = s.Receive(b);
char cc = ' ';
string test = null;
Console.WriteLine("Recieved1...");
for (int i = 0; i < k - 1; i++)
{
cc = Convert.ToChar(b[i]);
test += cc.ToString();
}
Console.WriteLine("Received characters1: "+test);
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("The string was recieved by the server."));
Console.WriteLine("\nSent Acknowledgement");
//s.Close(); <-if i enable this, i get a dispose error
k = s.Receive(b);//i get dispose error here
cc = ' ';
test = null;
Console.WriteLine("Recieved2...");
for (int i = 0; i < k - 1; i++)
{
cc = Convert.ToChar(b[i]);
test += cc.ToString();
}
Console.WriteLine("Received characters2: " + test);
/* clean up */
goto m;
s.Close();
myList.Stop();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.Message);
}
Console.ReadLine();
}
}
}
My client code is:
/******************************CLIENT*****************************************/
Socket socket = null;
try
{
Toast.makeText(context,"IP: "+ip+" port: "+port,10000).show();
InetAddress serverAddr = InetAddress.getByName(ip);
socket = new Socket(serverAddr, port);
}
catch (UnknownHostException e1)
{
Toast.makeText(context,"UnknownHostException ",10000).show();
}
catch (IOException e1)
{
Toast.makeText(context,"IOException ",10000).show();
}
String message = "1";
PrintWriter out = null;
BufferedReader in = null;
try {
Log.d("TCP", "C: Sending: '" + message + "'");
/*write*/
out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
out.println(message);
out.flush();
/*read*/
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String text = "";
String finalText = "";
while ((text = in.readLine()) != null)
{
finalText += text;
}
Toast.makeText(context, "FinalText: "+finalText, 10000).show();
Log.d("TCP", "C: Sent.");
Log.d("TCP", "C: Done.");
in.close();
/*write*/
out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
out.println(message);
out.flush();
} catch(Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Thanks advanced !!!
The reason you get the dispose error is because the s.close() closes the socket, and then your next s.Receive() is trying to read from a closed socket.
Also the hang you are seeing might be caused by in.close(); in your java code. It could be closing the underlying socket. Try commenting it out and see if that fixes your hanging problem.
Not an expert in C#, but I've done my share of socket programming.
Basically what you want is 1 + n threads.
One thread that just accepts connections.
For each socket that is returned by Socket s = myList.AcceptSocket(); you want a thread for sending/receiving data and processing the messages from the socket. You could also use two threads (one that sends, one that receives (this is the asynchronous case)).
You should use the stream of the tcp client.. an example can be found here: http://msdn.microsoft.com/de-de/library/system.net.sockets.tcplistener.aspx
And don't use goto, please.
You will never reach the end lines after goto m;
Surround the code with a while loop which checks if an timeout is occured or any other checks.
The reason why the server hangs is that he waits for 100 bytes to receive.
The problem was that when the client received the message from the server , in the while part entered into an infinite loop. I modify my app like this:
My client part:
try
{
Toast.makeText(context,"IP: "+ip+" port: "+port,10000).show();
InetAddress serverAddr = InetAddress.getByName(ip);
socket = new Socket(serverAddr, port);
}
catch (UnknownHostException e1)
{
Toast.makeText(context,"UnknownHostException ",10000).show();
}
catch (IOException e1)
{
Toast.makeText(context,"IOException ",10000).show();
}
String message = "HELLO FROM CLIENT";
PrintWriter out = null;
BufferedReader in = null;
try {
Log.d("TCP", "C: Sending: '" + message + "'");
/*write*/
OutputStream ostr=socket.getOutputStream();
OutputStreamWriter outputstr=new OutputStreamWriter(ostr);
BufferedWriter buffw=new BufferedWriter(outputstr);
out = new PrintWriter(buffw ,true);
out.println("HELLO 1 FROM CLIENT");
/*read - i modify to this*/
InputStreamReader reader=new InputStreamReader(socket.getInputStream());
char[] bytesreceived=new char[50];
reader.read(bytesreceived , 0, 50);
String text="";
for (int i=0;i<bytesreceived.length;i++)
{
text+=bytesreceived[i];
}
Toast.makeText(context, "Received1: "+text.trim(), 10000).show();
Log.d("IdealLog","Received1: "+text.trim());
/*write*/
out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
out.println("HELLO 2 FROM CLIENT");
/*read*/
reader=new InputStreamReader(socket.getInputStream());
bytesreceived=new char[50];
reader.read(bytesreceived , 0, 50);
text="";
for (int i=0;i<bytesreceived.length;i++)
{
text+=bytesreceived[i];
}
Toast.makeText(context, "Received2: "+text.trim(), 10000).show();
Log.d("IdealLog","Received2: "+text.trim());
} catch(Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
My server side code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace SocketServer
{
class Program
{
static void Main(string[] args)
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, 18001);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(ip);
socket.Listen(10);
Console.WriteLine("Waiting for a client...");
Socket client = socket.Accept();
IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}", clientep.Address, clientep.Port);
string welcome = "HELLO 1 FROM SERVER";
byte[] data = new byte[200];
int receiveddata=client.Receive(data);
Console.WriteLine("Received data from CLIENT1: {0}", System.Text.ASCIIEncoding.ASCII.GetString(data).Trim());
ASCIIEncoding asen = new ASCIIEncoding();
byte[] data2 = new byte[200];
data2 = asen.GetBytes(welcome);
int sentdata=client.Send(data2, data2.Length, SocketFlags.None);
Console.WriteLine("Sent data from SERVER: {0}", welcome);
byte[] data3 = new byte[200];
Console.WriteLine("Receiving data from CLIENT : {0}", "...");
client.Receive(data3);
Console.WriteLine("Received data from CLIENT2: {0}", System.Text.ASCIIEncoding.ASCII.GetString(data3).Trim());
byte[] data4 = new byte[200];
data4 = asen.GetBytes("HELLO 2 FROM SERVER");
sentdata = client.Send(data4, data4.Length, SocketFlags.None);
client.Close();
socket.Close();
Console.WriteLine("Disconnected from {0}", clientep.Address);
Console.ReadLine();
}
}
}
Now, everything is working fine, without hang. The only problem is, that i don't know if this will work for receiving , sending files.

Categories

Resources