I'm developing a server application where clients need to connect to.
But I don't want my users to enter an IP address... i want the Client to discover all servers running on port 4800 (in my case)
Here's my Server Code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
static ThreadStart ts = new ThreadStart(start_server);
Thread thread = new Thread(ts);
private void Form1_Load(object sender, EventArgs e)
{
thread.Start();
}
private static void start_server()
{
//Start server
Socket server = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
Console.Write("Running server..." + Environment.NewLine);
server.Bind(new IPEndPoint(IPAddress.Any, 4800));
while (true)
{
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint tempRemoteEP = (EndPoint)sender;
byte[] buffer = new byte[1000];
//Recive message from anyone.
server.ReceiveFrom(buffer, ref tempRemoteEP);
Console.Write("Server got '" + Encoding.ASCII.GetString(buffer).TrimEnd(new char[] { (char)0 }) +
"' from " + tempRemoteEP.ToString() +
Environment.NewLine);
string access_code = Encoding.ASCII.GetString(buffer).TrimEnd(new char[] { (char)0 });
if (access_code == "7uz876t5r798qwe12")
{
Console.Write("Sending Response to " + tempRemoteEP.ToString() +
Environment.NewLine);
//Replay to client
server.SendTo(Encoding.ASCII.GetBytes("ACCESS GRANTED"),
tempRemoteEP);
}
else
{
Console.WriteLine("Client Access denied!");
server.SendTo(Encoding.ASCII.GetBytes("ACCESS DENIED"),
tempRemoteEP);
}
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Environment.Exit(Environment.ExitCode);
}
}
and thats my client sending a UDP Broadcast:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
private void button1_Click(object sender, EventArgs e)
{
IPEndPoint AllEndPoint = new IPEndPoint(IPAddress.Broadcast, 4800);
//Allow sending broadcast messages
client.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.Broadcast, 1);
//Send message to everyone
client.SendTo(Encoding.ASCII.GetBytes("7uz876t5r798qwe12"), AllEndPoint);
Console.Write("Client send '1' to " + AllEndPoint.ToString() +
Environment.NewLine);
IPEndPoint _sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint tempRemoteEP = (EndPoint)_sender;
byte[] buffer = new byte[1000];
string serverIp;
try
{
client.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveTimeout, 3000);
client.ReceiveFrom(buffer, ref tempRemoteEP);
Console.Write("Client got '" + buffer[0] + "' from " +
tempRemoteEP.ToString() + Environment.NewLine);
MessageBox.Show(Encoding.ASCII.GetString(buffer).TrimEnd(new char[] { (char)0 }));
//Get server IP (ugly)
serverIp = tempRemoteEP.ToString().Split(":".ToCharArray(), 2)[0];
listServer.Items.Add(serverIp);
}
catch (Exception ex)
{
//Timout. No server answered.
MessageBox.Show(ex.Message);
}
// MessageBox.Show(serverIp);
}
}
All Servers running are Receiving the Broadcast, but my Client only receives 1 IP address. Maybe the first response that reaches the client?
How am I able to discover all my Servers listening on my Port?
Your client is calling ReceiveFrom() only once, so it is going to receive only one response. You need to call ReceiveFrom() in a loop instead, and run the loop for several seconds to give multiple servers enough time to respond.
Related
The form from this code does not appear. How can I get it to show? Through the console, everything works.
void Form1_Load(object sender, EventArgs e)
{
String host = Dns.GetHostName();//name kompa
//ip pc
IPAddress ip = Dns.GetHostByName(host).AddressList[0];
const int port = 2222;
label1.Text = host;
label2.Text = "Сервер запущен на " + ip.ToString() + ":" + port.ToString();
server.serversocket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
server.serversocket.Bind(new IPEndPoint(ip, port));
server.serversocket.Listen(100);
//ошибочка в цикле
while (server.work)
{
MessageBox.Show("dsff");
Socket handle = server.serversocket.Accept();
richTextBox1.AppendText("новое подключение" + handle.RemoteEndPoint.ToString());
new user(handle);
}
As Hans Passant said, you are blocking the GUI thread with a while loop. That will just not do. Events must return asap and can never run indefinitely. And this Form_Load can not return until the server stops working.
It is very common mistake and basically the reason we all went crazy for multitasking and multithreading this century. You can't even do a word processor without it anymore.
You are blocking the ui thread. Using a separate thread for the synchronous socket server would be a solution. The other option would be to use an asynchronous socket so that the execution of the application is not blocked while it waits for a connection. Based on the socket code samples.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitSocketServer();
}
internal void InitSocketServer()
{
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
var ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
try
{
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(localEndPoint);
listener.Listen(100);
listener.BeginAccept(AcceptCallback, listener);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void AcceptCallback(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
string data = null;
while (true)
{
var bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
if (data.IndexOf("<EOF>") > -1)
{
break;
}
}
MessageBox.Show(handler.RemoteEndPoint + " : " + data);
byte[] msg = Encoding.ASCII.GetBytes(data);
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Test button click");
}
}
I am creating a C# application in which I send files over a LAN connection via sockets, but I encounter an "System.NotSupportedException" when I call the Send function
This is the function of the receiver of the file.
Socket _newSocket;
List<byte> endBuffer;
// Used to connect to the server
private void button1_Click(object sender, EventArgs e)
{
_newSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_newSocket.Connect(IPAddress.Parse("127.0.0.1"), _PORT);
}
// Used to Receive the file
private void button3_Click(object sender, EventArgs e)
{
_newSocket.Receive(endBuffer.ToArray(), SocketFlags.None);
MessageBox
.Show(Encoding.ASCII.GetString(endBuffer.ToArray(), 0, endBuffer.Count));
}
This is the function I used to start the server.
void SetupServer(object sender)
{
Button temp = (Button)sender;
temp.Enabled = false;
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Bind(new IPEndPoint(IPAddress.Parse(txtConnectToIP.Text), _PORT));
_serverSocket.Listen(5);
_serverSocket.BeginAccept(AcceptCallback, null);
}
void AcceptCallback(IAsyncResult AR)
{
Socket socket;
try
{
socket = _serverSocket.EndAccept(AR);
}
catch
{
MessageBox.Show("Not Working!");
return;
}
_clientSockets.Add(socket);
int id = _clientSockets.Count - 1;
IPAddress ip = IPAddress.Parse(_serverSocket.LocalEndPoint.ToString().Split(':')[0]);
string HostName = Dns.GetHostEntry(ip).HostName.Split('.')[0];
string finalName = HostName + " (" + ip.ToString() + ")";
AddClientForSelectionCallback(finalName);
}
This is the send function.
byte[] postBuffer = Encoding.ASCII.GetBytes("Sending Complete!");
void Send(string filePath)
{
try
{
_serverSocket.SendFile(filePath, null, postBuffer, TransmitFileOptions.ReuseSocket);
}
catch (Exception ec)
{
MessageBox.Show("Failed with error message:\n "+ ec);
}
}
Lastly, how would Receive the file sent because _newSocket.Receive() does not seem to work. I have looked at storing its result in a var, but Receive returns nothing and I will try using ConnectAsync.
Help would really be appreciated.
In your program, _serverSocket is the socket that accepts incoming connections, you cannot send data to it.
As soon as a connection is accepted, you get the socket for that connection:
socket = _serverSocket.EndAccept(AR);
You can use this socket instance to communicate with that specific client.
I am battling to connect to a website using udpclient. Whenever I connect to localhost, I have no problems. This is the code I am using :'
private void button1_Click(object sender, EventArgs e)
{
UdpClient udpClient = new UdpClient();
udpClient.Connect("www.ituran.com/ituranmobileservice/mobileservice.asmx", 45004);
Byte[] btSendData = Encoding.ASCII.GetBytes("TESTING");
udpClient.Send(btSendData, btSendData.Length);
}
public void serverThread()
{
try
{
UdpClient udpClient = new UdpClient(45004);
while (true)
{
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] btRecieve = udpClient.Receive(ref RemoteIpEndPoint);
string strReturnData = Encoding.ASCII.GetString(btRecieve);
Console.WriteLine(RemoteIpEndPoint.Address.ToString() + ":" + strReturnData.ToString());
}
}
catch (Exception ex)
{
using (StreamWriter sw = new StreamWriter("TEST_errorLog.txt", true))
{
sw.WriteLine();
sw.WriteLine(ex.ToString());
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
Thread thdUDPServer = new Thread(new ThreadStart(serverThread));
thdUDPServer.IsBackground = true;
thdUDPServer.Start();
}
The people that sent me the URL has confimed five times that the address and port is correct. How can I connect to that address?
Any help would be appreciated.
Change the host name to just www.ituran.com. There are no paths in UDP - you are just sending packets to a port on a server.
I have implemented TCP hole punching in C#. What I am getting is, the clients are sending the SYN messages to each other but they are dropped at the opposite routers. The scenario is something like this:
Client:A--------Router:A--------Server--------Router:B--------Client:B
If client:A sends the SYN packet to Client:B, it is dropped at Router:B, which is obvious NAT behavior. But, according to the hole punch scenarios, now if the client:B sends SYN to client:A, it should pass through the NAT at router:A. Here in my case, router:A ,too, drops this packet. In netstat, it shows the conenction with B as SYN_SENT and after couple of seconds, I get a message like "The client has not been responding. Connection failure"
As per my research in this, reason behind dropping, may be silent dropping or active rejection. If it is silent dropping, then the hole should be punched and SYN from B should be passed through NAT at A. And if it is active rejection, the router:A will get the notification message from router:B about dropping and A will close the hole.
The problem is I am not getting any notification message at A. (checked through router log).
I also tried to an already implemented TCP hole pucnhing example taken from
https://github.com/jasonpang/tcp-holepunching
But I am getting the similar results. Help me to find out the solution for this.
I am also doubtful about the timeout for the holes punched at routers.
namespace HolePunching
{
public class HolePunchingClient
{
private Socket _clientSocket;
private Socket _serverSocket;
private Socket _connectSocket;
//private Socket _serverSocket;
private Socket _holePunchedSocket;
public HolePunchingClient (IPEndPoint localEndPoint)
{
/*For the moment, only TCP Hole Punching is supported*/
_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_clientSocket.Bind(localEndPoint);
//_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//_serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
//_serverSocket.Bind(localEndPoint);
}
private void ProcessClientRequest (object sender, DoWorkEventArgs eventArgs)
{
try
{
IPEndPoint iep = (IPEndPoint)eventArgs.Argument;
_connectSocket.Connect(iep);
Console.WriteLine("Connected correctly with: " + iep);
_serverSocket.Close();
_holePunchedSocket = _connectSocket;
Console.WriteLine("\n\n\nException check clientRequest\n\n\n");
}
catch (Exception e)
{
Console.WriteLine("In ProcessClientRequest: " + e.Message);
return;
}
}
private void ProcessServerRequest (object sender, DoWorkEventArgs eventArgs)
{
try
{
_serverSocket.Listen(10);
Socket s = _serverSocket.Accept();
Console.WriteLine("Received connection from: " + s.RemoteEndPoint);
_holePunchedSocket = s;
Console.WriteLine("\n\n\nException check serverRequest\n\n\n");
}
catch (Exception e)
{
Console.WriteLine("In ProcessServerRequest: " + e.Message);
return;
}
}
private void ProcessRequest (object sender, DoWorkEventArgs eventArgs)
{
while (true)
{
byte[] bytes = new byte[2048];
_clientSocket.Receive(bytes);
MessageType messageType = (MessageType) bytes[0];
Console.WriteLine("MessageType received: " + messageType);
switch (messageType)
{
case MessageType.ConnectClient:
byte[] byteAddress = new byte[4];
byte[] bytePort = new byte[2];
Buffer.BlockCopy(bytes, 1, byteAddress, 0, 4);
Buffer.BlockCopy(bytes, 5, bytePort, 0, 2);
IPEndPoint remoteEndPoint = new IPEndPoint(new IPAddress(byteAddress), BitConverter.ToUInt16(bytePort, 0));
Console.WriteLine("HP will be done towards this address: " + remoteEndPoint);
_connectSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_connectSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_connectSocket.Bind(_clientSocket.LocalEndPoint);
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_serverSocket.Bind(_clientSocket.LocalEndPoint);
BackgroundWorker bwClient = new BackgroundWorker();
bwClient.DoWork += ProcessClientRequest;
BackgroundWorker bwServer = new BackgroundWorker();
bwServer.DoWork += ProcessServerRequest;
bwClient.RunWorkerAsync(remoteEndPoint);
bwServer.RunWorkerAsync();
break;
}
}
}
public void Connect (IPEndPoint serverEndPoint)
{
_clientSocket.Connect(serverEndPoint);
_clientSocket.Send(BitConverter.GetBytes((byte)MessageType.Register));
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += ProcessRequest;
bw.RunWorkerAsync();
}
public Socket HolePunch (IPAddress otherAddress)
{
byte[] bytes = new byte[5];
Buffer.BlockCopy(BitConverter.GetBytes((byte)MessageType.RequestClient), 0, bytes, 0, 1);
Buffer.BlockCopy(otherAddress.GetAddressBytes(), 0, bytes, 1, 4);
_clientSocket.Send(bytes);
while (_holePunchedSocket == null)
{
System.Threading.Thread.Sleep(1500);
}
return _holePunchedSocket;
}
}
}
This is the client code, which I have taken from the link above. I'm getting the exception message "No response from another client. Connection failure" while connecting to the client B/A.
client A and B both run the same copies of this program. Either of them will send a request to server to connect with the other client. Server will send the IP-Port combination to both. and the client code will proceed by sending the connect request to each other.(which eventually gets timed out)
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