How to implement Socket server that accept more message - c#

I want to send at real time some data from Android application to server.
So I'm building a simple socket Server in c# like this:
class Program
{
private Socket listener;
static void Main(string[] args)
{
Program p = new Program();
p.socketServer();
}
public void socketServer()
{
int MAXBUFFER = 1024;
Console.WriteLine("SOCKET STARTED");
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.Any, 8080));
listener.Listen(10);
while (true)
{
Console.WriteLine("WAITING CONNECTION");
Socket socket = listener.Accept();
string receivedMessage = string.Empty;
while (true)
{
byte[] receivedBytes = new byte[MAXBUFFER];
int numBytes = socket.Receive(receivedBytes);
receivedMessage += Encoding.ASCII.GetString(receivedBytes, 0, numBytes);
if (receivedMessage.IndexOf("\n") > -1)
{
Console.WriteLine("MESSAGE FROM CLIENT: {0}", receivedMessage);
//break;
}
}
Console.WriteLine("MESSAGE FROM CLIENT: {0}", receivedMessage);
string replyMessage = "MESSAGE RECEIVED";
byte[] replyBytes = Encoding.ASCII.GetBytes(replyMessage);
}
}
public void shutdownServer()
{
listener.Shutdown(SocketShutdown.Both);
listener.Close();
}
}
And I'm building this class to send data from Android application:
public class TcpClient {
public static final String SERVER_IP = "192.168.110.50"; // computer IP address
public static final int SERVER_PORT = 8080;
private String mServerMessage;
private OnMessageReceived mMessageListener = null;
private boolean mRun = false;
private PrintWriter mBufferOut;
private BufferedReader mBufferIn;
private Socket socket;
/**
* Constructor of the class. OnMessagedReceived listens for the messages received from server
*/
public TcpClient(OnMessageReceived listener) {
mMessageListener = listener;
}
/**
* Sends the message entered by client to the server
*
* #param message text entered by client
*/
public void sendMessage(String message) {
socket.isConnected();
if (mBufferOut != null /*&& !mBufferOut.checkError()*/) {
mBufferOut.println(message);
}
}
/**
* Close the connection and release the members
*/
public void stopClient() {
Log.i("Debug", "stopClient");
// send mesage that we are closing the connection
//sendMessage(Constants.CLOSED_CONNECTION + "Kazy");
mRun = false;
if (mBufferOut != null) {
mBufferOut.flush();
mBufferOut.close();
}
mMessageListener = null;
mBufferIn = null;
mBufferOut = null;
mServerMessage = null;
}
public void run() {
mRun = true;
try {
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
//create a socket to make the connection with the server
socket = new Socket(SERVER_IP, SERVER_PORT);
//socket.connect(socket.getRemoteSocketAddress());
socket.isConnected();
try {
Log.i("Debug", "inside try catch");
mBufferOut = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
} catch (Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
And in the MainActivity I use this code:
tcpClient = new TcpClient(new TcpClient.OnMessageReceived() {
#Override
//here the messageReceived method is implemented
public void messageReceived(String message) {
//this method calls the onProgressUpdate
//publishProgress(message);
}
});
tcpClient.run();
After connect to server i user this code to send message:
for(int i=0; i<10; i++){
tcpClient.sendMessage("test " + i);
}
The problem is that only the first message arrive to the server. I think that the problem is on the socket server that lost the connection with the client.

Related

Thread sending data to wrong client. Is this a thread safety issue?

I'm currently developing a server that deals with clients using a consumer/producer approach with threads and a blocking collection as shown below:
public class NetworkClient
{
private bool _started = false;
private int _clientId;
private readonly Socket _socket;
private static AutoResetEvent _lastMessageWasAckd = new AutoResetEvent(true);
private static BlockingCollection<byte[]> _messageQueue = new BlockingCollection<byte[]>();
public NetworkClient(Socket socket, int clientId)
{
this._socket = socket;
this._clientId = clientId;
}
public int getClientID() {
return _clientId;
}
public void SendMessage(string message)
{
Console.WriteLine("Adding to player's sending queue " + _clientId);
_messageQueue.Add(Encoding.ASCII.GetBytes(message));
}
public void Start()
{
Thread receiver = new Thread(new ThreadStart(ReceivingThreadProc));
Thread sender = new Thread(new ThreadStart(SendingThreadProc));
receiver.Start();
sender.Start();
this._started = true;
}
public void Stop()
{
this._started = false;
}
private void ReceivingThreadProc()
{
byte[] bytes = new byte[1024];
string data;
try
{
while (_started && _socket.Connected)
{
int numByte = this._socket.Receive(bytes);
data = Encoding.ASCII.GetString(bytes, 0, numByte);
if (numByte == 0)
{
break;
}
if (data == "ACK")
{
_lastMessageWasAckd.Set();
continue;
}
// Acknowledge the message
_socket.Send(Encoding.ASCII.GetBytes("ACK"));
ServerReceiver.onEvent(this._clientId, data);
}
}
catch (Exception e)
{
this._socket.Close();
}
}
private void SendingThreadProc()
{
while (_started && _socket.Connected)
{
_lastMessageWasAckd.WaitOne();
byte[] message = _messageQueue.Take();
Console.WriteLine("Sending the following message to client number: " + _clientId);
Console.WriteLine(System.Text.Encoding.ASCII.GetString(message));
_socket.Send(message);
_lastMessageWasAckd.Reset();
}
}
}
There will be an instance of NetworkClient created for every client that connects for the server. The issue is that sometimes a message is queued to be sent to client 1 (this is confirmed by the Console.Writeline in the SendMessage method) however that message is sent to client 0 (Shown by the console writeline in the SendingThreadProc method) instead. Is this due to a thread safety issue, or am I missing something entirely? This typically happens when two messages are sent right after one another.
Any help would be greatly appreciated.
EDIT:
As many people rightly pointed out I haven't added where I call SendMessage I'll put this class down below:
class NetworkServer
{
private int latestClient = 0;
private ServerReceiver _serverReceiver;
private static readonly Dictionary<int, NetworkClient> clients = new Dictionary<int, NetworkClient>();
public NetworkServer()
{
IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 5656);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this._serverReceiver = new ServerReceiver();
this._serverReceiver.start();
try
{
listener.Bind(endpoint);
listener.Listen(10);
while (true)
{
Socket clientSocket = listener.Accept();
this.OnClientJoin(clientSocket);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static void SendClientMessage(int clientId, string package, CommandType commandType,
Dictionary<string, object> data = null)
{
if (data == null)
{
data = new Dictionary<string, object>();
}
SendClientMessageRaw(clientId, new NetworkCommand(clientId, package, commandType, data).ToJson());
}
public static void SendClientMessageRaw(int id, string message)
{
Console.WriteLine("Supposed to send to client number " + clients[id].getClientID());
clients[id].SendMessage(message);
}
private void OnClientJoin(Socket socket)
{
// Add client to array, perform handshake?
NetworkClient networkClient = new NetworkClient(socket, latestClient);
clients.Add(latestClient, networkClient);
Console.WriteLine("player added :" + latestClient);
networkClient.Start();
latestClient++;
if (latestClient == 2)
{
SendClientMessage(1, "Test", CommandType.Ping, null);
}
}
Could it be because your message queue is static and therefore shared between all NetworkClients? Meaning client A can pick up a message for client B?
Might be as easy as removing static from the properties.

Sockets - Not sending/receiving data

I'm starting a socket program, and am in the process of setting up a Server and two types of Clients (a requester and an arbiter). I'm in the middle of testing the connections, but they aren't quite working. Right now I just have a button for each form: an "Accept" button for the Arbiter and "Request" for the Requester. Each button should cause a popup on the other form, but neither is working. Also, I've noticed that when I close all programs, the Server is still running in my processes. What am I doing wrong?
Below is the Server code:
namespace FPPLNotificationServer
{
class Server
{
static Socket listenerSocket;
static List<ClientData> _clients;
static void Main(string[] args)
{
Console.WriteLine("Starting server on " + Packet.GetIP4Address());
listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_clients = new List<ClientData>();
IPEndPoint ip = new IPEndPoint(IPAddress.Parse(Packet.GetIP4Address()), 4242);
listenerSocket.Bind(ip);
Thread listenThread = new Thread(ListenThread);
listenThread.Start();
}
static void ListenThread()
{
for (;;)
{
listenerSocket.Listen(0);
_clients.Add(new ClientData(listenerSocket.Accept()));
}
}
public static void Data_IN(object cSocket)
{
Socket clientSocket = (Socket)cSocket;
byte[] Buffer;
int readBytes;
for (;;)
{
try
{
Buffer = new byte[clientSocket.SendBufferSize];
readBytes = clientSocket.Receive(Buffer);
if(readBytes > 0)
{
Packet packet = new Packet(Buffer);
DataManager(packet);
}
}catch(SocketException ex)
{
Console.WriteLine("Client Disconnected");
}
}
}
public static void DataManager(Packet p)
{
switch (p.packetType)
{
case Packet.PacketType.Notification:
foreach(ClientData c in _clients)
{
c.clientSocket.Send(p.ToBytes());
}
break;
}
}
}
class ClientData
{
public Socket clientSocket;
public Thread clientThread;
public string id;
public ClientData()
{
this.id = Guid.NewGuid().ToString();
clientThread = new Thread(Server.Data_IN);
clientThread.Start(clientSocket);
SendRegistrationPacket();
}
public ClientData(Socket clientSocket)
{
this.clientSocket = clientSocket;
this.id = Guid.NewGuid().ToString();
clientThread = new Thread(Server.Data_IN);
clientThread.Start(clientSocket);
SendRegistrationPacket();
}
public void SendRegistrationPacket()
{
Packet p = new Packet(Packet.PacketType.Registration, "server");
p.Gdata.Add(id);
clientSocket.Send(p.ToBytes());
}
}
}
ServerData
namespace FPPLNotificationServerData
{
[Serializable]
public class Packet
{
public List<String> Gdata;
public int packetInt;
public bool packetBool;
public string senderID;
public PacketType packetType;
public string PlantName, ProductSegment, ProductCustomer;
public int PlantNumber;
public string ProductNumber, ProductAltNumber;
public string ProductDiscription;
public int ProductLine;
public string ProductClass, ProductLocation;
public int ProductMcDFactor;
public Packet(PacketType type, String senderID)
{
Gdata = new List<string>();
this.senderID = senderID;
this.packetType = type;
}
public Packet(byte[] packetBytes)
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream(packetBytes);
Packet p = (Packet)bf.Deserialize(ms);
ms.Close();
this.Gdata = p.Gdata;
this.senderID = p.senderID;
this.packetType = p.packetType;
this.packetBool = p.packetBool;
this.packetInt = p.packetInt;
}
public byte[] ToBytes()
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, this);
byte[] bytes = ms.ToArray();
ms.Close();
return bytes;
}
public static string GetIP4Address()
{
IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());
foreach(IPAddress i in ips)
{
if(i.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
return i.ToString();
}
}
return "127.0.0.1";
}
public enum PacketType
{
Registration,
Chat,
Notification,
Request,
ArbiterDecision,
Accept,
Decline
}
}
}
Request Class:
namespace FPPLRequestClient
{
public partial class frm_Request : Form
{
public static Socket master;
public static string name;
public static string id;
public bool isConnected;
public frm_Request()
{
InitializeComponent();
string IP = "127.0.0.1";
master = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipEP = new IPEndPoint(IPAddress.Parse(IP), 4242);
try
{
master.Connect(ipEP);
isConnected = true;
}
catch (Exception)
{
isConnected = false;
}
string connectionStatus = isConnected ? "Connected" : "Disconnected";
this.lbl_Status.Text = "Status: " + connectionStatus;
Thread t = new Thread(Data_IN);
t.Start();
}
void Data_IN()
{
byte[] Buffer;
int readBytes;
while (isConnected)
{
try
{
Buffer = new byte[master.SendBufferSize];
readBytes = master.Receive(Buffer);
if(readBytes > 0)
{
DataManager(new Packet(Buffer));
}
}catch(SocketException ex)
{
isConnected = false;
this.Dispose();
}
}
}//END DATA IN
void DataManager(Packet p)
{
switch (p.packetType)
{
case Packet.PacketType.Registration:
id = p.Gdata[0];
break;
case Packet.PacketType.Accept:
//MessageBox.Show(p.ProductNumber);
this.lbl_Status.Text = p.ProductNumber + " accepted";
Invalidate();
break;
}
}
private void btn_Request_Click(object sender, EventArgs e)
{
Packet p = new Packet(Packet.PacketType.Request, id);
p.ProductNumber = "123456";
master.Send(p.ToBytes());
}
}
}
Arbiter Class:
namespace FPPLArbiterClient
{
public partial class frm_Arbiter : Form
{
public static Socket master;
public static string name;
public static string id;
public bool isConnected;
public frm_Arbiter()
{
InitializeComponent();
string IP = "127.0.0.1";
master = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipEP = new IPEndPoint(IPAddress.Parse(IP), 4242);
try
{
master.Connect(ipEP);
isConnected = true;
}
catch (Exception)
{
isConnected = false;
}
string connectionStatus = isConnected ? "Connected" : "Disconnected";
this.lbl_Status.Text = "Status: " + connectionStatus;
Thread t = new Thread(Data_IN);
t.Start();
}
void Data_IN()
{
byte[] Buffer;
int readBytes;
while (isConnected)
{
try
{
Buffer = new byte[master.SendBufferSize];
readBytes = master.Receive(Buffer);
if(readBytes > 0)
{
DataManager(new Packet(Buffer));
}
}catch(SocketException ex)
{
isConnected = false;
this.Dispose();
}
}
}//END DATA IN
void DataManager(Packet p)
{
switch (p.packetType)
{
case Packet.PacketType.Registration:
id = p.Gdata[0];
break;
case Packet.PacketType.Request:
MessageBox.Show(p.ProductNumber + " Requested from " + p.senderID);
break;
}
}
private void btn_Accept_Click(object sender, EventArgs e)
{
MessageBox.Show("Sending acceptance of 126456");
Packet p = new Packet(Packet.PacketType.Accept, id);
p.ProductNumber = "123456";
master.Send(p.ToBytes());
}
}
}
This is my first dive into socket programming.
To start with your last question first, Receive will block until data becomes available unless you specify a timeout. Since your threads are foreground threads, this will prevent your application from terminating. See https://msdn.microsoft.com/en-us/library/8s4y8aff(v=vs.110).aspx. Either use a timeout, and/or make your threads background threads causing them to terminate when you close your application's main thread. Set the created thread's IsBackground property to true to achieve this. (Also, in the article above notice the paragraph about Shutdown and the Receive method returning an empty array. This is your hint to gracefully close the connection on your side).
The TCP/IP stack will send data at its own discretion (Nagle's algorithm), meaning you'll occasionally receive a buffer containing several or partial messages. Since you have "silent" error handling in your thread, perhaps your thread terminates prematurely because of a corrupted message? Place everything you receive in a buffer and check the buffer for complete messages in a separate step/thread before passing them on to your message handler.
No clear answers here I'm afraid, but if the check for corrupted messages doesn't help, look at the Socket samples on MSDN. It's probably just a tiny detail you're missing.
you are making a fundamental and common TCP error. TCP is a byte oriented streaming protocol, not message oriented. Your receive code assumes that it receives one Packet when it reads. This is not guaranteed, you might receive 1 byte, 20 bytes, or whatever. You must loop in the receive till you get all of one message. This means you have to know when you have read it all. Either there needs to be a header or some sentinel at the end.

Multiple TcpListeners not working

I made an "Acceptor" class which in the cunstroctor it accepts an amount of TcpListeners. Starting from port 8484 and above.
class Acceptor
{
private List<TcpListener> Listeners;
private static int clientCount = 0;
private static int portStart = 8484;
public Acceptor(int capacity)
{
Listeners = new List<TcpListener>(capacity);
for (int i = 0; i < capacity; i++)
{
Listeners.Add(new TcpListener(IPAddress.Any, portStart));
portStart++;
}
foreach (TcpListener listener in Listeners)
{
try
{
listener.Start();
listener.BeginAcceptSocket(new AsyncCallback(EndAccept), null);
}
catch (SocketException ex)
{
Debug.WriteLine("Failed to start TcpListener, Error {0}.", ex.Message);
}
}
Debug.WriteLine(string.Format("Initiated {0} Listeners from 8484 - {1}.", capacity, portStart));
}
public void EndAccept(IAsyncResult IAR)
{
TcpListener Listener = (TcpListener)IAR.AsyncState;
Socket socket = Listener.EndAcceptSocket(IAR);
frmMain.Clients.Add(clientCount, new Client(socket));
Listener.Stop();
Listener = null;
clientCount++;
frmMain.Instance.UpdateClients();
}
}
However, that doesn't work. The program crashes when accepting a new connection, why's that?
You're passing null as the "state" in BeginAcceptSocket, thus the error when you attempt to cast it back and then use it.
Try changing this line:
listener.BeginAcceptSocket(new AsyncCallback(EndAccept), null);
To:
listener.BeginAcceptSocket(new AsyncCallback(EndAccept), listener);
This is how i implement a Listener:
public class EasySocketListener : IDisposable
{
private Socket _socket;
public void Start(int port)
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_socket.Bind(new IPEndPoint(IPAddress.Any, port));
_socket.Listen(1);
StartAccepting();
}
private void StartAccepting()
{
try
{
_socket.BeginAccept((asyncResult) =>
{
try
{
Socket clientSocket = _socket.EndAccept(asyncResult);
if (OnSocketAccept != null)
OnSocketAccept(this, new SocketEventArgs(clientSocket));
StartAccepting();
}
catch { }
}, null);
}
catch { }
}
public void Dispose()
{
if (_socket != null)
{
_socket.Dispose();
_socket = null;
}
}
public event EventHandler<SocketEventArgs> OnSocketAccept;
}
This can accept multiple client sockets. When a client connects, the OnSocketAccept triggers.
Needs the SocketEventArgs:
public class SocketEventArgs : EventArgs
{
public Socket Socket { get; private set; }
public SocketEventArgs(Socket socket)
{
Socket = socket;
}
}
example:
private void Init()
{
_listener = new EasySocketListener();
_listener.OnSocketAccept += Listener_OnSocketAccept;
_listener.Start(port);
}
private void Listener_OnSocketAccept(object sender, SocketEventArgs e)
{
Debug.WriteLine( e.Socket.RemoteEndPoint );
}
This will come on my blog http://csharp.vanlangen.biz but haven't wrote it there yet. You can find some methods for reading asynchronous from a socket.

Send data from android to C#

I want to send data from android to C#. C# is server. Android is client
I connect my computer to mobile's hotspot but i receive this error:
failed to connect to 192.168.1.15(port 4444):connect failed:ENETUNREACH(Network is unreachable
Here is the java code:
public class MainActivity extends Activity {
//TextView tv=(TextView) findViewById(R.id.textView2);
EditText edittext1;
private TCPClient mTcpClient;
private Button btnIP;
private TextView txt1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt1 = (TextView) findViewById(R.id.textView1);
final EditText editText = (EditText)findViewById(R.id.edit_message);
edittext1=(EditText) findViewById(R.id.editText1);
btnIP=(Button) findViewById(R.id.button1);
Button bt2=(Button) findViewById(R.id.button2);
bt2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
txt1.setText(TCPClient.log) ;
}
});
Button send = (Button)findViewById(R.id.send_button);
// connect to the server
new connectTask().execute("");
btnIP.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
TCPClient.SERVERIP=edittext1.getText().toString();
new connectTask().execute("");
}
});
send.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View view) {
String message = editText.getText().toString();
//sends the message to the server
if (mTcpClient != null)
{
mTcpClient.sendMessage(message);
}
editText.setText("");
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public class connectTask extends AsyncTask<String,String,TCPClient>
{
#Override
protected TCPClient doInBackground(String... message)
{
mTcpClient = new TCPClient(new OnMessageReceived()
{
#Override public void messageReceived(String message)
{
publishProgress(message);
}
});
Looper.prepare();
mTcpClient.run();
return null;
}
#Override
protected void onProgressUpdate(String... values)
{
super.onProgressUpdate(values);
}
}
public static class TCPClient
{
private String serverMessage;
public static String SERVERIP = "192.168.1.15";
public static final int SERVERPORT = 4444;
private OnMessageReceived mMessageListener = null;
public static String log="";
private boolean mRun = false;
PrintWriter out;
BufferedReader in;
DataOutputStream dataOutputStream = null;
//OutputStream os;
public TCPClient(OnMessageReceived listener)
{
mMessageListener = listener;
}
public void sendMessage(String message)
{
if (out != null && !out.checkError())
{
/* String toSend = "a"; byte[] toSendBytes = toSend.getBytes();
int toSendLen = toSendBytes.length; byte[] toSendLenBytes = new byte[4];
toSendLenBytes[0] = (byte)(toSendLen & 0xff); toSendLenBytes[1] = (byte)((toSendLen >> 8) & 0xff); toSendLenBytes[2] = (byte)((toSendLen >> 16) & 0xff); toSendLenBytes[3] = (byte)((toSendLen >> 24) & 0xff); try { os.write(toSendLenBytes); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } try { os.write(toSendBytes);
} catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } */
out.print(message);
out.flush();
}
}
public void stopClient()
{
mRun = false;
}
public void run()
{
// TextView tv=(TextView) findViewById(R.id.textView2);
//tv.setText(tv.getText()+"\n"+ "run");
mRun = true;
try
{
InetAddress serverAddr = InetAddress.getByName(SERVERIP);
Log.e("TCP Client", "C: Connecting...");
log="C: Connecting...";
//Toast.makeText(MainActivity.this, "Connecting", Toast.LENGTH_SHORT).show();
//tv.setText(tv.getText()+"\n"+ "Connecting");
//tv.setText(tv.getText()+"\n"+ "Connecting...");
Socket socket = new Socket(serverAddr, SERVERPORT);
/// //os = socket.getOutputStream();
if(socket.isBound())
{
Log.i("SOCKET", "Socket: Connected");
log="Connected";
//tv.setText(tv.getText()+"\n"+ "Connected");
//Toast.makeText(MainActivity.this, "Connected", Toast.LENGTH_SHORT).show();
//tv.setText(tv.getText()+"\n"+ "Connected");
}
else{
Log.e("SOCKET", "Socket: Not Connected");
log="Not Connected";
// tv.setText(tv.getText()+"\n"+ "not Connected");
//Toast.makeText(MainActivity.this, "not Connected", Toast.LENGTH_SHORT).show();
//tv.setText(tv.getText()+"\n"+ " Not Connected");
} try {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
//out.println(new char[]{'h','e'});
//out.flush();
/* dataOutputStream = new DataOutputStream(socket.getOutputStream()); byte[] bytes = new byte[] {1};
* dataOutputStream.write(bytes, 0, bytes.length); */
Log.e("TCP Client", "C: Sent.");
log=" Sent";
Log.e("TCP Client", "C: Done.");
log=" Done";
if(out.checkError())
{
Log.e("PrintWriter", "CheckError");
}
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (mRun)
{
serverMessage = in.readLine();
if (serverMessage != null && mMessageListener != null)
{
mMessageListener.messageReceived(serverMessage);
}
serverMessage = null;
}
Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + serverMessage + "'");
} catch (Exception e) { Log.e("TCP", "S: Error", e); }
finally { socket.close(); }
}
catch (Exception e) { Log.e("TCP", "C: Error", e);
log=e.getMessage();
//tv.setText(tv.getText()+"\n"+ e.getMessage());
}
}
}
}
C# code:
class Program
{
static private IPAddress getLocalIPAddress()
{
IPHostEntry host;
//string localIP = "";
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
// localIP = ip.ToString();
return ip;
//break;
}
}
// return localIP;
return null;
}
static void Main(string[] args)
{
int recv;
byte[] data = new byte[2048];
IPEndPoint ipep = new IPEndPoint(getLocalIPAddress(), 4444);
Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
newsock.Bind(ipep);
newsock.Listen(10);
Console.WriteLine("Waiting for a client...");
Socket client = newsock.Accept();
IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port{1}", clientep.Address, clientep.Port);
string welcome = "Welcome to my test server";
data = Encoding.ASCII.GetBytes(welcome);
client.Send(data, data.Length, SocketFlags.None);
while (true)
{
data = new byte[1024];
recv = client.Receive(data);
if (recv == 0)
break;
Console.WriteLine(Encoding.ASCII.GetString(data, 0,
recv));
client.Send(data, recv, SocketFlags.None);
}
Console.WriteLine("Disconnected from{0}", clientep.Address);
client.Close();
newsock.Close();
}
}

Send a Message Box to a client in my Domain from C# Windows Form

I have got a windows forms project than copying files and folders to clients in my domain. When copying file or copying directory process to [x]clients in my domain. I want to send it a Messagebox that says "There is a new folder or file in your [xdirectory]".
I can't do it by Messenger service because of Messenger service is does not working in XP Sp2 so I need another way for this. Maybe a client/server side application could be make. There will be a listener app in client then I will send it a messagebox.show code then it will show us a messagebox. etc.
I did something similar once before. I got most of this code from somewhere else, but I cannot remember from where.
First the Server Code:
public class HSTcpServer
{
private TcpListener m_listener;
private IPAddress m_address = IPAddress.Any;
private int m_port;
private bool m_listening;
private object m_syncRoot = new object();
public event EventHandler<TcpMessageReceivedEventArgs> MessageReceived;
public HSTcpServer(int port)
{
m_port = port;
}
public IPAddress Address
{
get { return m_address; }
}
public int Port
{
get { return m_port; }
}
public bool Listening
{
get { return m_listening; }
}
public void Listen()
{
try
{
lock (m_syncRoot)
{
m_listener = new TcpListener(m_address, m_port);
// fire up the server
m_listener.Start();
// set listening bit
m_listening = true;
}
// Enter the listening loop.
do
{
Trace.Write("Looking for someone to talk to... ");
// Wait for connection
TcpClient newClient = m_listener.AcceptTcpClient();
//Trace.WriteLine("Connected to new client");
// queue a request to take care of the client
ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessClient), newClient);
}
while (m_listening);
}
catch (SocketException se)
{
Trace.WriteLine("SocketException: " + se.ToString());
}
finally
{
// shut it down
StopListening();
}
}
public void StopListening()
{
if (m_listening)
{
lock (m_syncRoot)
{
// set listening bit
m_listening = false;
// shut it down
m_listener.Stop();
}
}
}
private void sendMessage(string message)
{
// Copy to a temporary variable to be thread-safe.
EventHandler<TcpMessageReceivedEventArgs> messageReceived = MessageReceived;
if (messageReceived != null)
messageReceived(this, new TcpMessageReceivedEventArgs(message));
}
private void ProcessClient(object client)
{
TcpClient newClient = (TcpClient)client;
try
{
// Buffer for reading data
byte[] bytes = new byte[1024];
StringBuilder clientData = new StringBuilder();
// get the stream to talk to the client over
using (NetworkStream ns = newClient.GetStream())
{
// set initial read timeout to 1 minute to allow for connection
ns.ReadTimeout = 60000;
// Loop to receive all the data sent by the client.
int bytesRead = 0;
do
{
// read the data
try
{
bytesRead = ns.Read(bytes, 0, bytes.Length);
if (bytesRead > 0)
{
// Translate data bytes to an ASCII string and append
clientData.Append(Encoding.ASCII.GetString(bytes, 0, bytesRead));
// decrease read timeout to 1 second now that data is
// coming in
ns.ReadTimeout = 1000;
}
}
catch (IOException ioe)
{
// read timed out, all data has been retrieved
Trace.WriteLine("Read timed out: {0}", ioe.ToString());
bytesRead = 0;
}
}
while (bytesRead > 0);
bytes = Encoding.ASCII.GetBytes("clowns");
// Send back a response.
ns.Write(bytes, 0, bytes.Length);
sendMessage(clientData.ToString());
}
}
finally
{
// stop talking to client
if (newClient != null)
newClient.Close();
}
}
}
public class TcpMessageReceivedEventArgs : EventArgs
{
private string m_message;
public TcpMessageReceivedEventArgs(string message)
{
m_message = message;
}
public string Message
{
get
{
return m_message;
}
}
}
The Client Code:
class HSTcpClient
{
private TcpClient _client;
private IPAddress _address;
private int _port;
private IPEndPoint _endPoint;
private bool _disposed;
public HSTcpClient(IPAddress address, int port)
{
_address = address;
_port = port;
_endPoint = new IPEndPoint(_address, _port);
}
public void SendForwardedClientMessage(int senderId, int receiverId, int hsId)
{
SendMessage(senderId.ToString() + ":" + receiverId.ToString() + ":" + hsId.ToString());
}
public void SendUpdatedCGBMessage()
{
SendMessage("Update your CGB you clowns");
}
public void SendMessage(string msg)
{
try
{
_client = new TcpClient();
_client.Connect(_endPoint);
// Get the bytes to send for the message
byte[] bytes = Encoding.ASCII.GetBytes(msg);
// Get the stream to talk to the server on
using (NetworkStream ns = _client.GetStream())
{
// Send message
Trace.WriteLine("Sending message to server: " + msg);
ns.Write(bytes, 0, bytes.Length);
// Get the response
// Buffer to store the response bytes
bytes = new byte[1024];
// Display the response
int bytesRead = ns.Read(bytes, 0, bytes.Length);
string serverResponse = Encoding.ASCII.GetString(bytes, 0, bytesRead);
Trace.WriteLine("Server said: " + serverResponse);
}
}
catch (SocketException se)
{
Trace.WriteLine("There was an error talking to the server: " +
se.ToString());
}
finally
{
Dispose();
}
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
System.GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
if (_client != null)
_client.Close();
}
_disposed = true;
}
}
#endregion
}
Then to use, create a server variable in your form code:
private HSTcpServer m_server;
and I created a background worker thread:
private System.ComponentModel.BackgroundWorker hsTcpServerThread;
handled the DoWork event:
private void hsTcpServerThread_DoWork(object sender, DoWorkEventArgs e)
{
m_server = new HSTcpServer(<pick your port>);
m_server.MessageReceived += new EventHandler<TcpMessageReceivedEventArgs>(m_server_MessageReceived);
m_server.Listen();
}
Then handle the message recieved event:
void m_server_MessageReceived(object sender, TcpMessageReceivedEventArgs e)
{
//<your code here> - e contains message details
}
Then to send a message to the server:
HSTcpClient client = new HSTcpClient(<ip address>, <port you picked>);
client.SendForwardedClientMessage(<message details>);
Hopefully I got everything in there.
You can use the FileSystemWatcher in the client. That way you do not have to deal with remoting or listening on ports.
If you really want to communicate between the two machines you can do using remoting, or via the TcpListener.

Categories

Resources