I'm trying to create a winforms application that listens for traffic on port 10000, and basically works as a middle man for a client application and a remote database. It should have a listen and accept thread which opens a separate client thread when a client connects. This client thread would then handle communication with the client program. The listener application has two listboxes with information on the user that is connecting and the action that is being performed.
For now, I'm trying to use the example program Microsoft gives here and modify it according to my needs, but if anyone has any suggestions on where else I might look I'd love to hear it.
As I try to stumble through this, one thing I haven't been able to figure out yet is how to get this listener going without locking down my computer. Here is my form code (including an exit button and a button that clears my listboxes):
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void btnExit_Click(object sender, EventArgs e) {
this.Close();
}
private void btnClearList_Click(object sender, EventArgs e) {
this.lbActionLog.Items.Clear();
this.lbUserLog.Items.Clear();
count = 0;
this.txtCount.Text = count.ToString();
}
private void Form1_Load(object sender, EventArgs e) {
Server begin = new Server();
begin.createListener();
}
}
and here is my listener code that is called with begin.createListener:
int servPort = 10000;
public void createListener() {
// Create an instance of the TcpListener class.
TcpListener tcpListener = null;
IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
string output = "";
try {
// Set the listener on the local IP address and specify the port.
//
tcpListener = new TcpListener(ipAddress, servPort);
tcpListener.Start();
output = "Waiting for a connection...";
}
catch (Exception e) {
output = "Error: " + e.ToString();
MessageBox.Show(output);
}
while (true) {
// Always use a Sleep call in a while(true) loop
// to avoid locking up your CPU.
Thread.Sleep(10);
// Create socket
//Socket socket = tcpListener.AcceptSocket();
TcpClient tcpClient = tcpListener.AcceptTcpClient();
// Read the data stream from the client.
byte[] bytes = new byte[256];
NetworkStream stream = tcpClient.GetStream();
stream.Read(bytes, 0, bytes.Length);
SocketHelper helper = new SocketHelper();
helper.processMsg(tcpClient, stream, bytes);
}
}
Right now, this just stops on tcpListener.AcceptSocket. The form never loads, and obviously the listboxes aren't being populated. How can I get this listener going automatically with the start of the application, and still load the form and update the listboxes? I want this application to start and be ready at any time to accept a connection, without needing to have one already sitting there waiting.
You are using a blocking method so that the Form1_Load never ends because it awaits incoming connections.
A simple workaround could be to start a new thread that handles connections:
private void Form1_Load(object sender, EventArgs e) {
new Thread(
() =>
{
Server begin = new Server();
begin.createListener();
}
).Start();
}
Related
I'm now trying to connect STM32F429 to C# desktop application with ESP8266(in STA mode). I want ESP8266 to be a client and C# to be a Server. However ESP8266 remains failing to find my PC in the same LAN.
Now I have succeeded to use AT command to connect ESP8266 to my Router AP. And I used XAMPP to open a gate on my PC whose address is 192.168.1.11:80, then use the following command (AT+CIPSTART=\"TCP\",\"192.168.1.11\",80") to successfully connect ESP8266 to it(It returned OK to my STM32F429).
Then I wanna replace XAMPP with my C# code to open a TCP server. But I couldn't make it!
As for the C# Code, I have successfully build a connection between two C# programs (The IP Address is 192.168.1.11:80 which is the same as the one mentioned above).But when I tried to use ESP8266 to connect to the same IP and Port, it failed.
I suspected that there might be some wrong conceptions I have got about opening a TCP Listener on certain port in my LAN... I don't know...
The following is my C# code. (The code of STM32 is just a basic Usart code which I won't present here.)
// Code for Server
namespace Tcp_Server
{
public partial class Form1 : Form
{
private TcpListener myListener;
private TcpClient newClient;
public BinaryReader br;
public BinaryWriter bw;
public Form1()
{
InitializeComponent();
Thread myThread = new Thread(ServerA);
myThread.Start();
}
private void ServerA()
{
IPAddress SvrIP = new IPAddress(Dns.GetHostByName(Dns.GetHostName()).AddressList[0].Address); // Get the virtual IP of my PC.
this.Invoke(new AddToTextbox_dg(AddToTextbox), new object[] { tb_ServerStatus, ip.ToString() });
myListener = new TcpListener(ip, 80); //construct a Tcp Listener.
myListener.Start(); //Tcp Listener start
newClient = myListener.AcceptTcpClient();// Searching for a client...
this.Invoke(new AddToTextbox_dg(AddToTextbox), new object[] { tb_ServerStatus, "Connect Successfully" });
while (true)
{
try
{
NetworkStream clientStream = newClient.GetStream();
br = new BinaryReader(clientStream);
string receive = null;
receive = br.ReadString();//读取
this.Invoke(new AddToTextbox_dg(AddToTextbox), new object[] { tb_ServerStatus, receive });
}
catch
{
MessageBox.Show("Receving failed...");
}
}
}
// Code for client
namespace Client
{
public partial class Form1 : Form
{
private TcpClient client;
public BinaryReader br;
public BinaryWriter bw;
public Form1()
{
InitializeComponent();
Thread myThread = new Thread(ClientA);
myThread.Start();
}
private void ClientA()
{
IPAddress ip = new IPAddress(Dns.GetHostByName(Dns.GetHostName()).AddressList[0].Address); // Get the virtual IP of my PC.
client = new TcpClient(ip.ToString(), 80);
this.Invoke(new AddToTextbox_dg(AddToTextbox), new object[] { tb_ServerStatus, "Connect to Server Successfully!" });
while (true)
{
try
{
NetworkStream clientStream = client.GetStream();
br = new BinaryReader(clientStream);
string receive = null;
receive = br.ReadString();
}
catch
{
MessageBox.Show("Receving failed...");
}
}
}
private void AddToTextbox(TextBox txt, String s)
{
txt.Text += s;
}
private delegate void AddToTextbox_dg(TextBox txt, String s);
private void btn_send_Click(object sender, EventArgs e)
{
NetworkStream clientStream = client.GetStream();
bw = new BinaryWriter(clientStream);
bw.Write(message.Text);
}
}
}
Could somebody please help me with this problem ?
I wonder why I cannot connect ESP8266 to the TcpListener I built on my PC with C#.
What did my PC do when receiving the command:
myListener = new TcpListener(ip, 80);
This project I'm doing is about to transmit the image data I got with Stm32F429 and OV7725 to my PC through ESP8266. I know Usart will be too slow to do that, but now I'm just trying to build the connection. Is there any suggestion you guys could give me about this?
First, make sure no other application on your pc is listening to port 80. if so, you have to change it.
Second, try setting the ip of the TCPListener to local host "127.0.0.1". you will be able to reach this server by connecting to the ip of your PC.
I have checked the used IP in command window as below:
Command Window for checking IP usage
And I remain the IP address which ESP8266 will try to access to be 192.168.1.11:1900 which is the virtual IP of my PC in the LAN as below:
Address ESP8266 try to access
And change the IP C# will try to create a TCPListener on:
C# code
Is this what you mean? Thank you.
I have a standalone test application developed in c# (4.5).
The application is primarily meant for sending some data to COM ports. The application accepts the data through the UI and the corresponding data is sent to respective COM ports.
For eg: Data from text box 1 goes to COM 1 on pressing a button, Data from Textbox 2 goes to COM 2 on pressing a different button etc.
Later I had to add a functionailty where a different set of data has to be accepted via Windows sockets and has to be sent to a different COM port other than above. This listening socket could receive data from multiple sources. If the listening socket receives back to back socket data, the application is expected to queue the data and process the data on a First come first serve bases.
Hence I created a synchronous socket to receive data. If the server receives data from 2 sources, it processes the data from source 1 and sends the completion status to source 1 and then takes the data from source 2,processes it and informs the status and this goes on. The socket is created on a thread so that it could receive and process data independently from the UI.
The application was meeting its objective as most of the communication was through sockets and people were not really using the UI for entering data.
Recently, as people started UI, i noticed a completely new issue. When someone tries to enters a data on to UI while the socket data is in process, it stops the socket data processing. When I press ctrl+Alt+Del on the host, it resumes the processing of the socket data.
I could not identify my mistake here. Also, I looked over to the Backgroundworkder class but I am not sure if that would allow the sockets commands to be processed in a synchronous way.
Please treat me as a newbie as I am still learning and complex suggestions might be hard to digest.
public partial class frm_bot : Form
{
public frm_bot()
{
StartServer();
}
private void frm_bot_Load(object sender, EventArgs e)
{
try
{
myThread = new System.Threading.Thread(new System.Threading.ThreadStart(OnClientConnect));
myThread.IsBackground = true;
myThread.Start();
}
catch (Exception ex)
{
showErrorMsg(ex.Message);
}//catch
}
public void StartServer()
{
InitializeComponent();
System.Net.IPAddress localIPAddress = System.Net.IPAddress.Parse(GetlocalIp());
IPEndPoint ipLocal = new IPEndPoint(localIPAddress, 8089);
_listener = new TcpListener(ipLocal);
}
private void OnClientConnect()
{
try
{
_listener.Start();
TcpClient clientSocket = default(TcpClient);
clientSocket = _listener.AcceptTcpClient();
_clientSocket = clientSocket;
ReadCallback();
}
catch (Exception se)
{
MessageBox.Show("Could not bind to Port 8089! Please close all Applications that uses Port 8089");
}
}
public void ReadCallback()
{
try
{
using (StreamReader sr = new StreamReader(_clientSocket.GetStream()))
using (StreamWriter sw = new StreamWriter(_clientSocket.GetStream()))
{
sw.AutoFlush = true;
char[] c = null;
while (sr.Peek() >= 0)
{
c = new char[25];
sr.Read(c, 0, c.Length);
Console.WriteLine(c);
}
string d = new string(c);
string[] cmddata = d.Split('\0');
string dataFromClient = cmddata[0];
if (dataFromClient.Length == 0)
{
Console.WriteLine("Client sent empty string!");
}
else
{
ProcessSocketData(dataFromClient);
sw.Write("Done");
}
sw.Close();
}
OnClientConnect();
}
catch (Exception ex)
{
OnClientConnect();
return;
}
}
public void ProcessSocketData(string sockdata)
{
try
{
// Socket data is processed here.
}
catch (Exception ex)
{
MessageBox.Show("Exception on ProcessSocketData: " + ex.Message);
return;
}
}
}
I have a simple WinForms app that is to serve as a server for multiple TelNet clients. When each one of these clients connects then a new thread is created. This is all working fine. However, I haven't found a suitable way to close these threads when I need to.
All the examples I have found online use Thread.Abort (which I know is a bad idea) or deal with threads created from the same class, which isn't what I need to do.
This is a simplified version of my classes:
Main UI class:
private void btnStart_Click(object sender, EventArgs e)
{
_listener = new TelNetListener(_deviceConnection);
}
private void btnStop_Click(object sender, EventArgs e)
{
// NEED TO SIGNAL Listener and all Client threads to stop here.
}
Listener class (thread created from Main UI class):
public TelNetListener(DeviceConnection deviceConnection)
{
Thread thread = new Thread(() => TelNetListenerStart(deviceConnection));
thread.Start();
}
private void TelNetListenerStart(DeviceConnection deviceConnection)
{
Socket listener;
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
listener.Bind(ipEndPoint);
listener.Listen(100);
_allDone = new ManualResetEvent(false);
while (true)
{
_allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallBack), listener);
_allDone.WaitOne();
}
}
private void AcceptCallBack()
{
telNetClient = new TelNetClient(clientSocket, string.Format("ACTN{0}",
_clientCounter.ToString("D4")));
}
Client class (thread created from Listener class):
public TelNetClient(Socket socket, string clientName)
{
Thread thread = new Thread(() => TelNetClientStart(socket, clientName));
thread.Start();
}
private void TelNetClientStart(Socket socket, string clientName)
{
DeviceConnection deviceConnection = new DeviceConnection();
this.ClientName = clientName;
this.State = new StateObject();
this.State.WorkSocket = socket;
Send(this.State, "Welcome...");
this.State.WorkSocket.BeginReceive(this.State.Buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallBack), this.State);
}
Bare in mind there is a fair amount of code missing, so if there are undeclared variables or anything like that, just ignore them. I just didn't want to put in loads of irrelevant code.
I have seen examples using a ManualResetEvent which seems to be what I need to do, but I'm not sure where to place it so that all the threads will work off it. Maybe I need 2, one for the Main class to signal the Listener class and from there another to signal all the Client classes?
Could anyone help me with this please as it is pretty much the last part of the infrastructure needed for this project.
If you need any more information I will try and provide it.
Change the code:
while (true)
{
_allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallBack), listener);
_allDone.WaitOne();
}
with some variable in your class which you can set.
while (this.Work)
{
_allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallBack), listener);
_allDone.WaitOne();
}
When you want to stop a listener you simply set the Work property to false.
I am using UdpClient class in .net 3.5
I need to bind multiple applications to the same port .
So, if UDP servers broadcast any request - all the applications thats listen on the port can receive the message but the problem is, when I try bind to an application to the same port, only one application receive the message and the other does not.
Below is some sample code for the two application:
UdpClient udpClient = new UdpClient();
Thread thread;
IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, 11000);
public Form1()
{
//CheckForIllegalCrossThreadCalls = false;
InitializeComponent();
udpClient.ExclusiveAddressUse = false;
udpClient.Client.SetSocketOption(
SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpClient.Client.Bind(endPoint);
}
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
thread.Abort();
udpClient.Close();
Close();
}
}
private void ReceiveMessage()
{
//while (true)
//{
// IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, 11000);
// byte[] content = udpClient.Receive(ref endPoint);
udpClient.BeginReceive(new AsyncCallback(Read_Callback), null);
//if (content.Length > 0)
//{
// string message = Encoding.ASCII.GetString(content);
// this.Invoke(myDelegate, new object[] { message });
//}
// }
}
public void Read_Callback(IAsyncResult ar)
{
try
{
byte[] buffer = udpClient.EndReceive(ar, ref endPoint);
// Process buffer
string s = Encoding.ASCII.GetString(buffer);
// richTextBox1.Text = s;
udpClient.BeginReceive(new AsyncCallback(Read_Callback), null);
}
catch (Exception ex)
{ }
}
PS : I am unable to figure out the reason or am I missing something. ?
That's the nature of sockets. Even in cases (such as UDP) where multiple applications can access the same port, the data is handed out first-come, first-serve. UDP is also designed with minimum overhead, so there isn't even an opportunity to "check the queue," like you (hypothetically) could with TCP.
It's designed around having multiple processes share a server load, alternating who receives the request based on who's idle.
You'd need to build something external to get around this, like a retransmission protocol or a database to make sure every inbound message is shared.
If you can deal with the changes, a smarter way to handle this would be UDP Multicast, where multiple programs essentially enroll to receive group messages. In that case, the single-port restriction can (and should) be abandoned.
Iam beginner to windows services , i have a console application to transfer files between client and server . Now i would like to turn my server application into windows services for listening multiple clients . I placed my console application code inside onstart() . After deploying the windows services not working or listening . Any IQ's...
Here is a complete article on TCP listener in windows service. It's quite old though but may be it helps.
hi i know this question is a long-standing one, and i checked many articles on stackoverflow or other sites, but there is no one make me satisfied. the most headache point is: it is a windows service, the while loop of listener should NOT be blocked when the service startup.
finally i made up a solution by myself, maybe maybe it is not system friendly, but it is quite simple and works fine ( I opened 3 telnet to this server concurrently, and it works as i wish) :-)
here is the code:
`protected override void OnStart(string[] args)
{
tcpServerStart();
}
private void tcpServerStart()
{
try
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
//port 5555, or any port number you want
listener = new TcpListener(ipAddress, 5555);
listener.Start();
var whileThread = new Thread(() =>
{
while (true)
{
// in order to avoid while loop turn into an infinite loop,
// we have to use AcceptTcpClient() to block it.
TcpClient client = listener.AcceptTcpClient();
// for each connection we just fork a thread to handle it.
var childThread = new Thread(() =>
{
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream(); // not blocking call
StreamReader streamreader = new StreamReader(client.GetStream(), Encoding.ASCII);
string line = null;
// below while loop is your logic code, change it to your needs.
// defined "<EOF>" as mine quit message
while ((line = streamreader.ReadLine()) != "<EOF>")
{
// WriteToFile is a function of mineto log system status
WriteToFile(line);
}
stream.Close();
client.Close();
});
childThread.Start();
} // end of while(true) loop
});
whileThread.Start();
}
catch (Exception e)
{
}
} '
this server open thread else never running service
protected override void OnStart(string[] args)
{
TcpServer server=new TcpServer();
server.Start();
}
class TcpServer
{
// clase prar crear un listener
private TcpListener server;
private bool isRunning;
private int port = 13000;
public void Start()
{
// client found.
// create a thread to handle communication
Thread tServer = new Thread(new ParameterizedThreadStart(StartThread));
tServer.Start();
}
public void StartThread(object o)
{
//iniciar configuraciones
Configuracion.init();
// crear un nuevo servidor
server = new TcpListener(IPAddress.Any, port);
//inicializar el servidor
server.Start();
//variable para indicar queesta corriendo el server
isRunning = true;
LoopClients();//thread
}}
public void LoopClients()
{
while (isRunning)
{
// wait for client connection
TcpClient newClient = server.AcceptTcpClient();
// client found.
// create a thread to handle communication
Thread t = new Thread(new ParameterizedThreadStart(HandleClient));
t.Start(newClient);
}
}