質問するログイン新規登録

回答編集履歴

1

別解掲載

2022/04/21 07:21

投稿

thkana
thkana

スコア7739

answer CHANGED
@@ -1,115 +1,169 @@
1
- 既存のライブラリを真面目に探せばもっといい処理もきそうな気がしますが、見つからなかった原始的にやってみまた。WiFiを繋だあとはCでソケットを扱う場合の定番にほぼ沿ったものです
2
-
3
- ```Arduino
4
- #include <sys/select.h>
5
- #include <sys/socket.h>
6
- #include <WiFi.h>
7
-
8
- static const char *WIFI_SSID = "WROOM32";
9
- static const char *WIFI_PASS = "password";
10
- const int port = 1337;
11
-
12
- int fd, maxfd;
13
- int fd2[2] = { -1, -1}; //二口だけ接続をうけつける
14
- struct sockaddr_in addr;
15
- struct sockaddr_in from_addr;
16
- struct timeval tv;
17
-
18
- //サーバー設定-------------------------------------------------
19
- IPAddress ip(192, 168, 1, 10);
20
- //-------------------------------------------------------------
21
-
22
- void setup() {
23
- Serial.begin(115200);
24
- //Wi-Fiアクセスポイント開始--------------------------------------------------------
25
- WiFi.mode(WIFI_AP);
26
- WiFi.softAP(WIFI_SSID, WIFI_PASS);
27
- WiFi.softAPConfig(ip, WiFi.gatewayIP(), WiFi.subnetMask());
28
- //WiFi.softAPConfig(ip, gateway, netmask);
29
-
30
- IPAddress myIP = WiFi.softAPIP();
31
- Serial.println("APStarted. myIP Address:");
32
- Serial.println(myIP);
33
- Serial.print("server Mac Address: ");
34
- Serial.println(WiFi.macAddress());
35
- Serial.print("Subnet Mask: ");
36
- Serial.println(WiFi.subnetMask());
37
- Serial.print("Gateway IP: ");
38
- Serial.println(WiFi.gatewayIP());
39
- //------------------------------------------------------------------------------
40
-
41
- if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
42
- Serial.println("socket error.");
43
- while (1);
44
- }
45
- addr.sin_family = AF_INET;
46
- addr.sin_port = ntohs(port);
47
- addr.sin_addr.s_addr = INADDR_ANY;
48
- if ( bind( fd, (struct sockaddr *)&addr, sizeof(addr)) < 0 ) {
49
- Serial.println( "bind error" );
50
- while (1);
51
- }
52
-
53
- }
54
-
55
-
56
- void loop() {
57
- if ( listen(fd, 1) < 0) {
58
- Serial.println("listen error.");
59
- }
60
-
61
- fd_set fds;
62
- FD_ZERO(&fds);
63
- FD_SET( fd, &fds);
64
- maxfd = fd;
65
- for (int i = 0; i < 2; i++) {
66
- if (fd2[i] != -1) {
67
- FD_SET(fd2[i], &fds);
68
- if (fd2[i] > fd) {
69
- maxfd = fd2[i];
70
- }
71
- }
72
- }
73
- tv.tv_sec = 0;
74
- tv.tv_usec = 10000;
75
- int cnt = select(maxfd + 1, &fds, NULL, NULL, &tv);
76
- if (cnt <= 0) {
77
- //error or timeout
78
- for (int i = 0; i < 2; i++) {
79
- if (fd2[i] >= 0) {
80
- //既接続のソケットに対して送信
81
- char buf[32];
82
- cnt = sprintf(buf, "To %d %ld\n", fd2[i], millis());
83
- write(fd2[i], buf, cnt);
84
- }
85
- }
86
- }
87
- if (FD_ISSET( fd, &fds)) {
88
- for (int i = 0; i < 2; i++) {
89
- //接続受付
90
- if (fd2[i] == -1) {
91
- socklen_t len = sizeof(struct sockaddr_in);
92
- if ((fd2[i] = accept(fd, (struct sockaddr *)&from_addr, &len)) < 0) {
93
- Serial.println("accept error.");
94
- while (1);
95
- }
96
- Serial.println("connect " + String( fd2[i]));
97
- break;
98
- }
99
- }
100
- }
101
- for (int i = 0; i < 2; i++) {
102
- if (fd2[i] != -1 && FD_ISSET(fd2[i], &fds) ) {
103
- //受信&接続断検出
104
- char buf[256];
105
- int rcvCnt = recv(fd2[i], buf, sizeof(buf), 0);
106
- Serial.println("rcvd:" + String(buf));
107
- if (rcvCnt < 0) {
108
- Serial.println("disconnect " + String(fd2[i]));
109
- close(fd2[i]);
110
- fd2[i] = -1;
111
- }
112
- }
113
- }
114
- }
115
- ```
1
+ 2022年4月現在で'ESP32 複数 クライアント'ググったらこれがトップヒットしちゃって...ちょっと恥ずかしいかな
2
+ 普通にArduinoライブラリでもできちゃったので、一応そちらも載せておきます。二口分の受け方は「ベタ」に書いているので、実際になにかするなら美しくまとめてください。もちろん、動作中にreadStringUntil()とかでブロックしたりしちゃいけませんよ。
3
+ ```Arduino
4
+ #include <WiFi.h>
5
+ WiFiServer server(54321);
6
+
7
+ void setup() {
8
+ Serial.begin(115200);
9
+ WiFi.begin(); //引数省略で最後に接続したAPにつなぎに行く。WiFiの接続とソケットの接続を混同しないようにしましょう。
10
+ while (WiFi.status() != WL_CONNECTED) {
11
+ delay(500);
12
+ }
13
+ Serial.println(WiFi.localIP());
14
+ server.begin();
15
+ }
16
+ WiFiClient client[2];
17
+ String s[2];
18
+ void loop() {
19
+ if( !client[0].connected()){
20
+ client[0]= server.available();
21
+ if(client[0].connected()){
22
+ Serial.println("Connected to 0");
23
+ client[0].println("Connected to 0");
24
+ }
25
+ }else{
26
+ while(client[0].available()){
27
+ char c=client[0].read();
28
+ s[0]+=c;
29
+ if(c=='\n'){
30
+ Serial.println(s[0]);
31
+ client[0].print(s[0]);
32
+ }
33
+ }
34
+ }
35
+ if( !client[1].connected()){
36
+ client[1]= server.available();
37
+ if(client[1].connected()){
38
+ Serial.println("Connected to 1");
39
+ client[1].println("Connected to 1");
40
+ }
41
+ }else{
42
+ while(client[1].available()){
43
+ char c=client[1].read();
44
+ s[1]+=c;
45
+ if(c=='\n'){
46
+ Serial.println(s[1]);
47
+ client[1].print(s[1]);
48
+ }
49
+ }
50
+ }
51
+ }
52
+ ```
53
+ 以下原文
54
+ ---
55
+ 既存のライブラリを真面目に探せばもっといい処理もできそうな気がしますが、見つからなかったので原始的にやってみました。WiFiを繋いだあとはCでソケットを扱う場合の定番にほぼ沿ったものです。
56
+
57
+ ```Arduino
58
+ #include <sys/select.h>
59
+ #include <sys/socket.h>
60
+ #include <WiFi.h>
61
+
62
+ static const char *WIFI_SSID = "WROOM32";
63
+ static const char *WIFI_PASS = "password";
64
+ const int port = 1337;
65
+
66
+ int fd, maxfd;
67
+ int fd2[2] = { -1, -1}; //二口だけ接続をうけつける
68
+ struct sockaddr_in addr;
69
+ struct sockaddr_in from_addr;
70
+ struct timeval tv;
71
+
72
+ //サーバー設定-------------------------------------------------
73
+ IPAddress ip(192, 168, 1, 10);
74
+ //-------------------------------------------------------------
75
+
76
+ void setup() {
77
+ Serial.begin(115200);
78
+ //Wi-Fiアクセスポイント開始--------------------------------------------------------
79
+ WiFi.mode(WIFI_AP);
80
+ WiFi.softAP(WIFI_SSID, WIFI_PASS);
81
+ WiFi.softAPConfig(ip, WiFi.gatewayIP(), WiFi.subnetMask());
82
+ //WiFi.softAPConfig(ip, gateway, netmask);
83
+
84
+ IPAddress myIP = WiFi.softAPIP();
85
+ Serial.println("APStarted. myIP Address:");
86
+ Serial.println(myIP);
87
+ Serial.print("server Mac Address: ");
88
+ Serial.println(WiFi.macAddress());
89
+ Serial.print("Subnet Mask: ");
90
+ Serial.println(WiFi.subnetMask());
91
+ Serial.print("Gateway IP: ");
92
+ Serial.println(WiFi.gatewayIP());
93
+ //------------------------------------------------------------------------------
94
+
95
+ if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
96
+ Serial.println("socket error.");
97
+ while (1);
98
+ }
99
+ addr.sin_family = AF_INET;
100
+ addr.sin_port = ntohs(port);
101
+ addr.sin_addr.s_addr = INADDR_ANY;
102
+ if ( bind( fd, (struct sockaddr *)&addr, sizeof(addr)) < 0 ) {
103
+ Serial.println( "bind error" );
104
+ while (1);
105
+ }
106
+
107
+ }
108
+
109
+
110
+ void loop() {
111
+ if ( listen(fd, 1) < 0) {
112
+ Serial.println("listen error.");
113
+ }
114
+
115
+ fd_set fds;
116
+ FD_ZERO(&fds);
117
+ FD_SET( fd, &fds);
118
+ maxfd = fd;
119
+ for (int i = 0; i < 2; i++) {
120
+ if (fd2[i] != -1) {
121
+ FD_SET(fd2[i], &fds);
122
+ if (fd2[i] > fd) {
123
+ maxfd = fd2[i];
124
+ }
125
+ }
126
+ }
127
+ tv.tv_sec = 0;
128
+ tv.tv_usec = 10000;
129
+ int cnt = select(maxfd + 1, &fds, NULL, NULL, &tv);
130
+ if (cnt <= 0) {
131
+ //error or timeout
132
+ for (int i = 0; i < 2; i++) {
133
+ if (fd2[i] >= 0) {
134
+ //既接続のソケットに対して送信
135
+ char buf[32];
136
+ cnt = sprintf(buf, "To %d %ld\n", fd2[i], millis());
137
+ write(fd2[i], buf, cnt);
138
+ }
139
+ }
140
+ }
141
+ if (FD_ISSET( fd, &fds)) {
142
+ for (int i = 0; i < 2; i++) {
143
+ //接続受付
144
+ if (fd2[i] == -1) {
145
+ socklen_t len = sizeof(struct sockaddr_in);
146
+ if ((fd2[i] = accept(fd, (struct sockaddr *)&from_addr, &len)) < 0) {
147
+ Serial.println("accept error.");
148
+ while (1);
149
+ }
150
+ Serial.println("connect " + String( fd2[i]));
151
+ break;
152
+ }
153
+ }
154
+ }
155
+ for (int i = 0; i < 2; i++) {
156
+ if (fd2[i] != -1 && FD_ISSET(fd2[i], &fds) ) {
157
+ //受信&接続断検出
158
+ char buf[256];
159
+ int rcvCnt = recv(fd2[i], buf, sizeof(buf), 0);
160
+ Serial.println("rcvd:" + String(buf));
161
+ if (rcvCnt < 0) {
162
+ Serial.println("disconnect " + String(fd2[i]));
163
+ close(fd2[i]);
164
+ fd2[i] = -1;
165
+ }
166
+ }
167
+ }
168
+ }
169
+ ```