c# 多个 tcpclients 使其中一个客户端断开连接几秒钟
c# multiple tcpclients makes one of the client disconnects for few sec
我正在尝试制作一个机器人。为此,我需要大约 6 个 arduino 以太网,它们连接到连接到计算机的 Cisco 集线器。我的 C# 代码是基于线程的,因此它可以处理多个客户端。工作完成后,服务器断开连接,然后客户端重新连接。客户端在 100 毫秒时连接-断开连接-重新连接。在此arduino以太网不断发送和接收数据。所有连接都在端口 23 上建立。每个客户端都有不同的 IP 地址。
问题:
最初,当我启动服务器时,所有这些都获得连接,但几秒钟后,其中一个冻结 3-4 秒,之后它获得连接,但当它重新连接时,其他一些将处于冻结状态。
如果我将 arduino 代码的延迟从 100 毫秒增加到 400 毫秒,所有这些都可以正常连接。但对于我的机器人过程,我需要它以 100 毫秒的速度工作。
我无法弄清楚 aduino 以太网这种奇怪行为的原因。已经完成了所有的基本测试,并且在某个地方感觉到了它的 arduino 问题。
以下是我的 c# 和我的 arduino 代码(所有 6 个代码都相同,只是发送和接收的数据不同)
C#代码:
using System.Threading;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace client_server_demo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
// input data is stored into s
string receiving_data = "";
int port_no = 23;
// the index of %
int receiving_data_length;
// sonar sensors data
int[] sonar_sensor_data = { 0, 0, 0, 0 };
bool[] limit_switch = { false, false, false, false };
// data to arduinos
string sending_data = "";
byte[] c1;
//store ipaddress of connected client
string ipaddress_client = "";
//error msg of disconnection
string disconnect_error = "";
/// <summary>
/// start of the form
/// </summary>
public MainWindow()
{
InitializeComponent();
Thread tcpthread = new Thread(new ThreadStart(tcpserverRun));
tcpthread.Start();
}
/// <summary>
/// connects to the clients on port 23
/// </summary>
private void tcpserverRun()
{
TcpListener tcplistener = new TcpListener(IPAddress.Any, port_no);
updateUi("listening");
tcplistener.Start();
while (true)
{
TcpClient client = tcplistener.AcceptTcpClient();
updateUi("connected");
//for multiple clients use thread
Thread tcpHandlerThread = new Thread(new ParameterizedThreadStart(tcphandler));
tcpHandlerThread.Start(client);
}
}
private void tcphandler(object client)
{
try
{
TcpClient mclient = (TcpClient)client; // create client
Socket so = mclient.Client; // create a socket so as to get the ipaddress of the client
NetworkStream stream = mclient.GetStream();
//read data from the port
byte[] message = new byte[100];
stream.Read(message, 0, message.Length);
receiving_data = Encoding.ASCII.GetString(message);
receiving_data_length = receiving_data.IndexOf('%');
//remove garbage ahead of %
receiving_data = receiving_data.Substring(0, receiving_data_length + 1);
//get ipaddress of the client connected
ipaddress_client = (IPAddress.Parse(((IPEndPoint)so.RemoteEndPoint).Address.ToString())).ToString();
// show the string on ui -> ip addres+ data
updateUi(ipaddress_client + " : " + receiving_data);
//send data
if (receiving_data == "R%")
{
//send to the arduino
sending_data = "Welcome client 1 %";
ASCIIEncoding asen = new ASCIIEncoding();
c1 = asen.GetBytes(sending_data);
stream.Write(c1, 0, c1.Length);
}
if (receiving_data == "S%")
{
sending_data = "Welcome client 2 %";
ASCIIEncoding asen = new ASCIIEncoding();
c1 = asen.GetBytes(sending_data);
stream.Write(c1, 0, c1.Length);
}
if (receiving_data == "L%")
{
sending_data = "Welcome client 3 %";
ASCIIEncoding asen = new ASCIIEncoding();
c1 = asen.GetBytes(sending_data);
stream.Write(c1, 0, c1.Length);
}
if (receiving_data == "T%")
{
sending_data = "Welcome client 4 %";
ASCIIEncoding asen = new ASCIIEncoding();
c1 = asen.GetBytes(sending_data);
stream.Write(c1, 0, c1.Length);
}
if (receiving_data == "J%")
{
sending_data = "Welcome client 5 %";
ASCIIEncoding asen = new ASCIIEncoding();
c1 = asen.GetBytes(sending_data);
stream.Write(c1, 0, c1.Length);
}
if (receiving_data == "A%")
{
sending_data = "Welcome client 6 %";
ASCIIEncoding asen = new ASCIIEncoding();
c1 = asen.GetBytes(sending_data);
stream.Write(c1, 0, c1.Length);
}
//clos al the streams and client so as to avaoid memory leakage
stream.Flush();
stream.Close();
mclient.Close();
}
catch (Exception e)
{
updateException(e.StackTrace);
}
}
/// <summary>
/// for updating the form as per data received from the clients
/// </summary>
/// <param name="s"></param>
private void updateUi(string s)
{
Func<int> del = delegate()
{
textBox1.AppendText(s + System.Environment.NewLine);
label1.Content = "connected";
label2.Content = "";
textBox1.ScrollToEnd();
return 0;
};
Dispatcher.Invoke(del);
}
/// <summary>
/// for showing if any error occurred
/// </summary>
/// <param name="s"></param>
private void updateException(string s)
{
Func<int> del = delegate()
{
label1.Content = "";
label2.Content = "Error : " + s;
return 0;
};
Dispatcher.Invoke(del);
}
}
在arduino代码中,在led的帮助下我知道它是否接收到数据。如果计时器没有从服务器获取数据,它就会保持跟踪,然后它会保持 LED 亮起。否则它在闪烁。如果未连接到服务器,则关闭。
arduino code:
#include "Wire.h"
#include "I2Cdev.h" // libraries
#include <SPI.h>
#include <Ethernet.h>
#include <SimpleTimer.h>
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
}
;
char server[] = "192.168.0.50"; //ipaddress of the joystick ethernet
IPAddress ip(192, 168, 0, 53); //ipaddress of this ethernet
EthernetClient client;
char inChar; //for reading bytes received from the server
String inputString = "";
int cleaning_state=0; //for getting the mode selected
int firstcomma=0,secondcomma=0; //for separating data
SimpleTimer timer; //for timer
int received_full_string=0; //to indicate where full data is recieved or not where 0= partial data 1= full data
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(9, OUTPUT);
digitalWrite(9, LOW);
Ethernet.begin(mac, ip);
delay(1000);
if (client.connect(server, 23)) // if client is connected on server 24
{
Serial.write("como");
}
else
{
Serial.write("disconn");
}
//cal a timer every 1s
timer.setInterval(1000, RepeatTask);
}
void loop() {
timer.run(); //start the timer
//chek if client is connected if not than try to reconnect otherwise read data from it
if (client.connected())
{
client.print("R%"); //for handshaking
while(client.available()>0)
{
inChar = (char)client.read();
inputString += inChar; //concat for string
if(inChar == '%')
{
Serial.println(inputString);
received_full_string=1; //indicating full data is recieved
digitalWrite(9, HIGH); // blink the led if received full data
// further processing
}
}
delay(10);
}
else
{
client.stop();
Serial.write("disconnected");
delay(10);
if (client.connect(server, 23))
{
Serial.write("re-connected");
}
}
delay(100);
//if full data is received than while exiting the loop make led turn off
if(received_full_string == 1)
{
digitalWrite(9, LOW);
}
inputString="";
}
//when timer is called check if the full data is received if yes than make the received_full_string=0 if no than stop the process
void RepeatTask()
{
if(received_full_string == 1)
{
received_full_string=0;
}
else
{
Serial.println("stop");
digitalWrite(9, HIGH);
}
}
我们将不胜感激任何形式的帮助。
谢谢
问题解决了,不是 c# 代码也不是 arduino 代码错误,而是 mac 地址。
每个 arduino 以太网都需要有唯一的 ip 和 mac 地址
我正在尝试制作一个机器人。为此,我需要大约 6 个 arduino 以太网,它们连接到连接到计算机的 Cisco 集线器。我的 C# 代码是基于线程的,因此它可以处理多个客户端。工作完成后,服务器断开连接,然后客户端重新连接。客户端在 100 毫秒时连接-断开连接-重新连接。在此arduino以太网不断发送和接收数据。所有连接都在端口 23 上建立。每个客户端都有不同的 IP 地址。
问题:
最初,当我启动服务器时,所有这些都获得连接,但几秒钟后,其中一个冻结 3-4 秒,之后它获得连接,但当它重新连接时,其他一些将处于冻结状态。
如果我将 arduino 代码的延迟从 100 毫秒增加到 400 毫秒,所有这些都可以正常连接。但对于我的机器人过程,我需要它以 100 毫秒的速度工作。
我无法弄清楚 aduino 以太网这种奇怪行为的原因。已经完成了所有的基本测试,并且在某个地方感觉到了它的 arduino 问题。
以下是我的 c# 和我的 arduino 代码(所有 6 个代码都相同,只是发送和接收的数据不同)
C#代码:
using System.Threading;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace client_server_demo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
// input data is stored into s
string receiving_data = "";
int port_no = 23;
// the index of %
int receiving_data_length;
// sonar sensors data
int[] sonar_sensor_data = { 0, 0, 0, 0 };
bool[] limit_switch = { false, false, false, false };
// data to arduinos
string sending_data = "";
byte[] c1;
//store ipaddress of connected client
string ipaddress_client = "";
//error msg of disconnection
string disconnect_error = "";
/// <summary>
/// start of the form
/// </summary>
public MainWindow()
{
InitializeComponent();
Thread tcpthread = new Thread(new ThreadStart(tcpserverRun));
tcpthread.Start();
}
/// <summary>
/// connects to the clients on port 23
/// </summary>
private void tcpserverRun()
{
TcpListener tcplistener = new TcpListener(IPAddress.Any, port_no);
updateUi("listening");
tcplistener.Start();
while (true)
{
TcpClient client = tcplistener.AcceptTcpClient();
updateUi("connected");
//for multiple clients use thread
Thread tcpHandlerThread = new Thread(new ParameterizedThreadStart(tcphandler));
tcpHandlerThread.Start(client);
}
}
private void tcphandler(object client)
{
try
{
TcpClient mclient = (TcpClient)client; // create client
Socket so = mclient.Client; // create a socket so as to get the ipaddress of the client
NetworkStream stream = mclient.GetStream();
//read data from the port
byte[] message = new byte[100];
stream.Read(message, 0, message.Length);
receiving_data = Encoding.ASCII.GetString(message);
receiving_data_length = receiving_data.IndexOf('%');
//remove garbage ahead of %
receiving_data = receiving_data.Substring(0, receiving_data_length + 1);
//get ipaddress of the client connected
ipaddress_client = (IPAddress.Parse(((IPEndPoint)so.RemoteEndPoint).Address.ToString())).ToString();
// show the string on ui -> ip addres+ data
updateUi(ipaddress_client + " : " + receiving_data);
//send data
if (receiving_data == "R%")
{
//send to the arduino
sending_data = "Welcome client 1 %";
ASCIIEncoding asen = new ASCIIEncoding();
c1 = asen.GetBytes(sending_data);
stream.Write(c1, 0, c1.Length);
}
if (receiving_data == "S%")
{
sending_data = "Welcome client 2 %";
ASCIIEncoding asen = new ASCIIEncoding();
c1 = asen.GetBytes(sending_data);
stream.Write(c1, 0, c1.Length);
}
if (receiving_data == "L%")
{
sending_data = "Welcome client 3 %";
ASCIIEncoding asen = new ASCIIEncoding();
c1 = asen.GetBytes(sending_data);
stream.Write(c1, 0, c1.Length);
}
if (receiving_data == "T%")
{
sending_data = "Welcome client 4 %";
ASCIIEncoding asen = new ASCIIEncoding();
c1 = asen.GetBytes(sending_data);
stream.Write(c1, 0, c1.Length);
}
if (receiving_data == "J%")
{
sending_data = "Welcome client 5 %";
ASCIIEncoding asen = new ASCIIEncoding();
c1 = asen.GetBytes(sending_data);
stream.Write(c1, 0, c1.Length);
}
if (receiving_data == "A%")
{
sending_data = "Welcome client 6 %";
ASCIIEncoding asen = new ASCIIEncoding();
c1 = asen.GetBytes(sending_data);
stream.Write(c1, 0, c1.Length);
}
//clos al the streams and client so as to avaoid memory leakage
stream.Flush();
stream.Close();
mclient.Close();
}
catch (Exception e)
{
updateException(e.StackTrace);
}
}
/// <summary>
/// for updating the form as per data received from the clients
/// </summary>
/// <param name="s"></param>
private void updateUi(string s)
{
Func<int> del = delegate()
{
textBox1.AppendText(s + System.Environment.NewLine);
label1.Content = "connected";
label2.Content = "";
textBox1.ScrollToEnd();
return 0;
};
Dispatcher.Invoke(del);
}
/// <summary>
/// for showing if any error occurred
/// </summary>
/// <param name="s"></param>
private void updateException(string s)
{
Func<int> del = delegate()
{
label1.Content = "";
label2.Content = "Error : " + s;
return 0;
};
Dispatcher.Invoke(del);
}
}
在arduino代码中,在led的帮助下我知道它是否接收到数据。如果计时器没有从服务器获取数据,它就会保持跟踪,然后它会保持 LED 亮起。否则它在闪烁。如果未连接到服务器,则关闭。
arduino code:
#include "Wire.h"
#include "I2Cdev.h" // libraries
#include <SPI.h>
#include <Ethernet.h>
#include <SimpleTimer.h>
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
}
;
char server[] = "192.168.0.50"; //ipaddress of the joystick ethernet
IPAddress ip(192, 168, 0, 53); //ipaddress of this ethernet
EthernetClient client;
char inChar; //for reading bytes received from the server
String inputString = "";
int cleaning_state=0; //for getting the mode selected
int firstcomma=0,secondcomma=0; //for separating data
SimpleTimer timer; //for timer
int received_full_string=0; //to indicate where full data is recieved or not where 0= partial data 1= full data
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(9, OUTPUT);
digitalWrite(9, LOW);
Ethernet.begin(mac, ip);
delay(1000);
if (client.connect(server, 23)) // if client is connected on server 24
{
Serial.write("como");
}
else
{
Serial.write("disconn");
}
//cal a timer every 1s
timer.setInterval(1000, RepeatTask);
}
void loop() {
timer.run(); //start the timer
//chek if client is connected if not than try to reconnect otherwise read data from it
if (client.connected())
{
client.print("R%"); //for handshaking
while(client.available()>0)
{
inChar = (char)client.read();
inputString += inChar; //concat for string
if(inChar == '%')
{
Serial.println(inputString);
received_full_string=1; //indicating full data is recieved
digitalWrite(9, HIGH); // blink the led if received full data
// further processing
}
}
delay(10);
}
else
{
client.stop();
Serial.write("disconnected");
delay(10);
if (client.connect(server, 23))
{
Serial.write("re-connected");
}
}
delay(100);
//if full data is received than while exiting the loop make led turn off
if(received_full_string == 1)
{
digitalWrite(9, LOW);
}
inputString="";
}
//when timer is called check if the full data is received if yes than make the received_full_string=0 if no than stop the process
void RepeatTask()
{
if(received_full_string == 1)
{
received_full_string=0;
}
else
{
Serial.println("stop");
digitalWrite(9, HIGH);
}
}
我们将不胜感激任何形式的帮助。 谢谢
问题解决了,不是 c# 代码也不是 arduino 代码错误,而是 mac 地址。 每个 arduino 以太网都需要有唯一的 ip 和 mac 地址