質問編集履歴

6

放置する通信が再開する旨を追加

2022/12/09 07:59

投稿

TAKE_SS
TAKE_SS

スコア40

test CHANGED
File without changes
test CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  正常に受信している間はなんともないのですが、急にAndroidに受信が届かなくなる(受信出来ない)事象があり、困っています。10分程度で発生するときもありますが、長いと1時間半後に発生するなど,発生するまでの時間に統一性はみられません。
6
6
  サーバー側は送信を続けており、特にエラーにはなっていません。
7
+
8
+ この状態を放置してずっと受信待ちにしていると、受信が再開する場合があるようです。
7
9
 
8
10
  また、同じアプリをAndroid7の端末で動かすと特に問題は発生しません。
9
11
  受信するクライアントをPC側に別アプリで動かしても特に問題はありません。

5

ソース一部追記&修正

2022/12/08 23:55

投稿

TAKE_SS
TAKE_SS

スコア40

test CHANGED
File without changes
test CHANGED
@@ -262,6 +262,9 @@
262
262
  ```
263
263
  クライアント側2:Android(xamarin) この受信処理でもReceiveDataCallbackが来なくなっている
264
264
  ```C#
265
+ public class SockClient
266
+ {
267
+
265
268
  /// <summary>
266
269
  /// 同期オブジェクト(Socket同時使用防止用)
267
270
  /// </summary>
@@ -309,13 +312,16 @@
309
312
  }
310
313
   }
311
314
 
315
+  string errMsg = $"切断:{Me.IPEndPoint?.Address.ToString()}({Me.IPEndPoint?.Port})";
316
+  Debug.Print(errMsg);
317
+
318
+  OnDisconnect?.Invoke(this, Me);
319
+  Me.clSock = null;
320
+  Me.IPEndPoint = null;
321
+
312
322
   sock.Close();
313
323
   sock.Dispose();
314
-  OnDisconnect?.Invoke(this, Me);
315
-  string errMsg = $"切断:{Me.IPEndPoint?.Address.ToString()}({Me.IPEndPoint?.Port})";
316
-  Debug.Print(errMsg);
317
-  Me.clSock = null;
318
-  Me.IPEndPoint = null;
319
- }
324
+ }
325
+
320
-
326
+ }
321
327
  ```

4

ソース追加

2022/12/08 23:27

投稿

TAKE_SS
TAKE_SS

スコア40

test CHANGED
File without changes
test CHANGED
@@ -260,3 +260,62 @@
260
260
  }
261
261
 
262
262
  ```
263
+ クライアント側2:Android(xamarin) この受信処理でもReceiveDataCallbackが来なくなっている
264
+ ```C#
265
+ /// <summary>
266
+ /// 同期オブジェクト(Socket同時使用防止用)
267
+ /// </summary>
268
+ private object syncSocket = new object();
269
+
270
+ private void ReceiveCallback(IAsyncResult ar)
271
+ {
272
+ Debug.Print("【ReceiveCallback】受信");
273
+ int bytes;
274
+ // 自インスタンス取得
275
+ SockClient Me = (SockClient)ar.AsyncState;
276
+ // ソケット取得
277
+ Socket sock = Me.clSock;
278
+ // 既に閉じられている場合は終了
279
+ if ((sock == null) || (!sock.Connected))
280
+ {
281
+ Debug.Print("【ReceiveCallback】Socketが閉じている");
282
+ return;
283
+ }
284
+
285
+ try
286
+ {
287
+ // クライアントソケットから受信データを取得終了
288
+ lock (syncSocket) bytes = sock.EndReceive(ar);
289
+ }
290
+ catch(Exception ex)
291
+ {
292
+     Debug.Print("【ReceiveCallback】EndReceiveエラー:" + ex.Message);
293
+     bytes = 0;
294
+ }
295
+   if (bytes > 0)
296
+ {
297
+ // 受信処理
298
+ onReceiveAll(Me, bytes);
299
+ try
300
+ {
301
+ // 受信時のコードバック処理を再設定
302
+ lock (syncSocket) sock.BeginReceive(Me.Buffer, 0, BuffSize, 0, new AsyncCallback(ReceiveCallback), Me);
303
+ Debug.Print("【ReceiveCallback】onReceiveAll & BeginReceive ");
304
+ return;
305
+ }
306
+ catch {
307
+ string Msg = $"例外:{Me.IPEndPoint?.Address.ToString()}({Me.IPEndPoint?.Port})";
308
+  Debug.Print(errMsg);
309
+ }
310
+  }
311
+
312
+  sock.Close();
313
+  sock.Dispose();
314
+  OnDisconnect?.Invoke(this, Me);
315
+  string errMsg = $"切断:{Me.IPEndPoint?.Address.ToString()}({Me.IPEndPoint?.Port})";
316
+  Debug.Print(errMsg);
317
+  Me.clSock = null;
318
+  Me.IPEndPoint = null;
319
+ }
320
+
321
+ ```

3

ソース一部追加

2022/12/08 23:10

投稿

TAKE_SS
TAKE_SS

スコア40

test CHANGED
File without changes
test CHANGED
@@ -114,6 +114,22 @@
114
114
  ```C#
115
115
  private static Socket TcpClient = null
116
116
 
117
+ // 同期ソケット用クラス
118
+ class AsyncStateObject
119
+ {
120
+ public Socket socket;
121
+ public byte[] buffer; // 受信バッファ
122
+ public byte[] WkBuffer; // 処理用のバッファ
123
+ public int WkLen; // 処理途中のレングス
124
+ public AsyncStateObject(System.Net.Sockets.Socket soc)
125
+ {
126
+ this.socket = soc;
127
+ this.buffer = new byte[1024];
128
+ this.WkBuffer = new byte[0];
129
+ this.WkLen = 0;
130
+ }
131
+ }
132
+
117
133
  <オープン>
118
134
  TcpClient = new Socket(SocketType.Stream, 0);
119
135
  TcpClient .ReceiveTimeout = 5000;

2

ソースコード追加

2022/12/08 07:03

投稿

TAKE_SS
TAKE_SS

スコア40

test CHANGED
File without changes
test CHANGED
@@ -25,3 +25,222 @@
25
25
  ・Android7端末とAndroid9端末で同じアプリを動かしてみると、Android9の方だけ受信が来なくなってしまう
26
26
  ・wifiの接続を2.4Gから5Gに変更しても、頻度が変わるが発生する
27
27
   (たまたまの可能性があるが、2.4Gの方が頻度が高かった)
28
+
29
+ ### ソースコード
30
+ サーバー側(Windows7)
31
+ ```C
32
+ bool CNetSv::Create(int nPort, HANDLE evtClose, CWnd *pPair/* = nullptr*/)
33
+ {
34
+ if (nPort == 0){
35
+ return true;
36
+ }
37
+ m_nPort = nPort;
38
+ m_evtClose = evtClose;
39
+ m_pPair = pPair;
40
+ if (!CAsyncSocket::Create(nPort)){
41
+ return false;
42
+ }
43
+ if (!Listen()){
44
+ return false;
45
+ }
46
+
47
+ m_bConnect = true;
48
+
49
+ return true;
50
+ }
51
+
52
+ void CNetSv::OnAccept(int nErrorCode)
53
+ {
54
+ CNetCl *pCL;
55
+ sockaddr_in saAddr;
56
+ int nLen = sizeof(saAddr);
57
+ if (nErrorCode != 0){
58
+ return;
59
+ }
60
+
61
+ // 空き番を探して登録
62
+ for (int i = 0; i < 50; i++){
63
+ if (m_mapCL.find(i) == m_mapCL.end()){
64
+ pCL = new CNetCl(i, m_evtClose, m_pPair);
65
+ Accept(*pCL, (SOCKADDR*)&saAddr, &nLen);
66
+ pCL->SetAddr(saAddr.sin_addr);
67
+ m_mapCL[i] = pCL;
68
+ break;
69
+ }
70
+ }
71
+
72
+ CAsyncSocket::OnAccept(nErrorCode);
73
+ }
74
+ void CNetSv::Send(LPCTSTR szData, size_t nSize)
75
+ {
76
+ std::map<int, CNetCl*>::iterator it = m_mapCL.begin();
77
+
78
+ // 接続がない場合は終了
79
+ if (!m_bConnect)return;
80
+
81
+ // 送信先がない場合は終了
82
+ if (m_mapCL.size() <= 0) return;
83
+
84
+ // データにSTX,ETX,BCCを付ける
85
+ char *szSend;
86
+ char cBCC = 0;
87
+
88
+ szSend = new char[nSize + 4]; // STX,ETX,BCC,NULL分を付加
89
+
90
+ // STX付加
91
+ szSend[0] = STX;
92
+ // データをコピー(+BCC計算)
93
+ for (size_t i = 0; i < nSize; i++) {
94
+ szSend[i + 1] = szData[i];
95
+ cBCC ^= szData[i];
96
+ }
97
+ // ETX付加
98
+ szSend[nSize + 1] = ETX;
99
+ // BCC付加
100
+ szSend[nSize + 2] = cBCC ^ETX;
101
+
102
+ // 全接続にデータ送信
103
+ while (it != m_mapCL.end()) {
104
+ it->second->Send(szSend, nSize + 3);
105
+ ++it;
106
+ }
107
+
108
+ delete[] szSend;
109
+ }
110
+
111
+ ```
112
+
113
+ クライアント側:Android(xamarin)
114
+ ```C#
115
+ private static Socket TcpClient = null
116
+
117
+ <オープン>
118
+ TcpClient = new Socket(SocketType.Stream, 0);
119
+ TcpClient .ReceiveTimeout = 5000;
120
+ TcpClient .SendTimeout = 5000;
121
+ TcpClient .Connect(Address, Port);  // AddressはIPアドレス、Portは9900等
122
+
123
+ <受信コールバック>
124
+ private void ReceiveDataCallback(System.IAsyncResult ar)
125
+ {
126
+ //状態オブジェクトの取得
127
+ AsyncStateObject so = (AsyncStateObject)ar.AsyncState;
128
+ DateTime dNow = DateTime.Now;
129
+ Log.Debug("【ReceiveDataCallback】", "受信" + dNow.ToString("mm:ss.fff"));
130
+
131
+ //読み込んだ長さを取得
132
+ int len = 0;
133
+ try
134
+ {
135
+ len = so.socket.EndReceive(ar);
136
+ }
137
+ catch (Exception e)
138
+ {
139
+ //閉じた時
140
+ var strError = e.Message;
141
+ Log.Debug("【ReceiveDataCallback】", "接続が閉じました。:" + strError );
142
+ if (so.socket != null)
143
+ {
144
+ so.socket.Close();
145
+ TcpClient = null;
146
+ }
147
+ return;
148
+ }
149
+
150
+ //切断されたか調べる
151
+ if (len <= 0)
152
+ {
153
+ // エラー通知
154
+ Log.Debug("【ReceiveDataCallback】", "接続が切断されました。");
155
+ if (so.socket != null)
156
+ {
157
+ so.socket.Close();
158
+ TcpClient = null;
159
+ }
160
+ return;
161
+ }
162
+
163
+ try
164
+ {
165
+ //受信したデータを蓄積する
166
+ int DataSize = so.WkLen + len; // 処理レングス算出(前回の残り+今回受信)
167
+ Array.Resize(ref so.WkBuffer, DataSize + 1); // 処理用バッファをリサイズ(前回の残り+今回受信+1)
168
+ Array.Copy(so.buffer, 0, so.WkBuffer, so.WkLen, len);
169
+ byte[] rcvDataWk = new byte[DataSize];
170
+ byte[] restData = new byte[DataSize]; // 未処理データが残った場合の待避用
171
+ int nRecv = 0; // 処理済みデータレングス
172
+ for (int i = 0; i < DataSize; i++)
173
+ {
174
+ if ((so.WkBuffer[i] == STX) && (m_eRecv != RCVTYPE.chek))
175
+ {
176
+ m_cBcc = 0; // bcc初期化
177
+ Array.Clear(rcvDataWk, 0, rcvDataWk.Length);
178
+ m_nRecv = 0;
179
+ m_eRecv = RCVTYPE.recv; // 受信中
180
+ }
181
+ else if ((so.WkBuffer[i]) == ETX && (m_eRecv == RCVTYPE.recv))
182
+ {
183
+ rcvDataWk[m_nRecv] = 0x0;
184
+ m_cBcc ^= so.WkBuffer[i];
185
+ m_eRecv = RCVTYPE.chek; // BCC待ち
186
+ }
187
+ else if (m_eRecv == RCVTYPE.chek) // BCCチェック
188
+ {
189
+ if (so.WkBuffer[i] == m_cBcc) // BCC一致
190
+ {
191
+ DataProc(ref rcvDataWk, m_nRecv);
192
+ nRecv = nRecv + (m_nRecv + 3); // 未処理データレングス算出
193
+ }
194
+ m_eRecv = RCVTYPE.none;
195
+ }
196
+ else
197
+ {
198
+ rcvDataWk[m_nRecv++] = so.WkBuffer[i];
199
+ m_cBcc ^= so.WkBuffer[i];
200
+ if (m_nRecv > 4095)
201
+ {
202
+ m_nRecv = 0;
203
+ m_eRecv = RCVTYPE.none;
204
+ }
205
+ }
206
+ }
207
+
208
+ if (m_eRecv != RCVTYPE.none) // 受信処理未完(データ途中)
209
+ {
210
+ int nRestLen = DataSize - nRecv; // 未処理データレングス算出(受信データ-処理済みデータ)
211
+ if (nRecv > 0) // 処理済みがあるとき(受信が多かったとき)
212
+ {
213
+ Array.Copy(so.WkBuffer, nRecv, restData, 0, nRestLen); // 待避用バッファに残りをコピー
214
+ Array.Resize(ref so.WkBuffer, nRestLen + 1); // 処理用バッファをリサイズ(残りのみ)
215
+ Array.Clear(so.WkBuffer, 0, nRestLen + 1);
216
+ Array.Copy(restData, 0, so.WkBuffer, 0, nRestLen); // 待避したデータを戻す
217
+ }
218
+ so.WkLen = nRestLen; // 途中のレングス保存
219
+ m_eRecv = RCVTYPE.none; // 状態クリア(次回は先頭から解析)
220
+ }
221
+ else
222
+ {
223
+ so.WkLen = 0;
224
+ m_nRecv = 0;
225
+ }
226
+ }
227
+ catch (Exception ex)
228
+ {
229
+ var strError = ex.Message;
230
+ Log.Debug("【ReceiveDataCallback】", "Exception"+ex.Message);
231
+ m_eRecv = RCVTYPE.none;
232
+ so.WkLen = 0;
233
+ m_nRecv = 0;
234
+ }
235
+
236
+ //再び受信開始
237
+ so.socket.BeginReceive(
238
+ so.buffer,
239
+ 0,
240
+ so.buffer.Length,
241
+ System.Net.Sockets.SocketFlags.None,
242
+ new System.AsyncCallback(ReceiveDataCallback),
243
+ so);
244
+ }
245
+
246
+ ```

1

試したこと追記

2022/12/07 05:37

投稿

TAKE_SS
TAKE_SS

スコア40

test CHANGED
File without changes
test CHANGED
@@ -23,5 +23,5 @@
23
23
  ・回線をいったんクローズして再オープンするとどうなるか
24
24
   ⇒ 正常に受信が開始される
25
25
  ・Android7端末とAndroid9端末で同じアプリを動かしてみると、Android9の方だけ受信が来なくなってしまう
26
-
26
+ ・wifiの接続を2.4Gから5Gに変更しても、頻度が変わるが発生する
27
-
27
+  (たまたまの可能性があるが、2.4Gの方が頻度が高かった)