質問編集履歴
6
放置する通信が再開する旨を追加
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
ソース一部追記&修正
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
ソース追加
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
ソース一部追加
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
ソースコード追加
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
試したこと追記
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の方が頻度が高かった)
|