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

質問編集履歴

1

コードがクライアント側でした申し訳ありません

2019/06/26 05:34

投稿

akiya_0608
akiya_0608

スコア14

title CHANGED
File without changes
body CHANGED
@@ -7,82 +7,89 @@
7
7
  サーバー:
8
8
  ```C#
9
9
  class Program
10
- {
10
+ {
11
- //====================================================
12
- //Client
13
- //====================================================
14
-
15
11
  static void Main(string[] args)
16
12
  {
13
+ //Server
14
+ BaseServer listener = new BaseServer();
17
- Console.WriteLine("入力してください");
15
+ listener.Init("127.0.0.1", 12345);
18
- string sendMsg = Console.ReadLine();
16
+ var task = listener.StartAccept();
19
17
 
20
- //ipアドレスとポート番号設定
21
- string ipOrHost = "127.0.0.1";
22
- int port = 12345;
23
-
24
- //sendData
25
- System.Text.Encoding enc = System.Text.Encoding.UTF8;
26
- byte[] body = enc.GetBytes(sendMsg);
27
-
28
- //通信
29
- BaseSocket sock = new BaseSocket();
30
- sock.Init(ipOrHost, port);
31
- sock.StartRecvThread(); //非同期通信Recv
32
-
33
-
34
-
35
-
36
18
  while (true)
37
19
  {
38
- sock.Send(body, body.Length);
39
- sock.Update();
20
+ listener.BeginUpdate();
21
+
40
- while (sock.RecvDataSize() > 0)
22
+ if (listener.clientList.Count > 0)
41
23
  {
24
+ foreach (TcpRecvServer client in listener.clientList)
25
+ {
26
+ while (client.RecvDataListCount() > 0)
27
+ {
42
- byte[] data = sock.GetRecvData();
28
+ byte[] data = client.GetRecvDataList();
29
+ if(client.Send(data, data.Length)<0)
30
+ {
31
+ break;
32
+ }
43
- string text = System.Text.Encoding.UTF8.GetString(data);
33
+ Console.WriteLine("data合計={0}", client.RecvDataListCount());
34
+ }
35
+ }
36
+ }
44
37
 
45
- Console.WriteLine("recvDataSize={0},data={1}", data.Length, text);
38
+ listener.EndUpdate();
46
- }
47
39
  }
48
40
 
49
41
  }
50
- }
51
42
 
52
-
43
+ }
53
-
54
-
55
-
56
- class BaseSocket
44
+ class TcpRecvServer
57
45
  {
46
+ public const int BUFSIZE = 2048;
47
+ object lockObj = new object();
48
+ public Socket socket { get; }
49
+ public byte[] ReceiveBuffer;
58
- private List<byte> recvTempDataList = new List<byte>();
50
+ public List<byte> recvTempDataList = new List<byte>();
59
- private List<byte[]> recvDataList=new List<byte[]>();
51
+ public List<byte[]> recvDataList = new List<byte[]>();
60
- //ソケット作成
61
- private System.Net.Sockets.TcpClient tcp;
62
- private System.Net.Sockets.NetworkStream ns;
63
- private Object lockObject = new Object();
64
- private bool deleteFlg = false;
52
+ public bool deleteFlg { get; private set; } = false;
53
+ public bool threadDeleteFlg { get; private set; } = false;
54
+ public TcpRecvServer(Socket _socket)
55
+ {
56
+ socket = _socket;
57
+ ReceiveBuffer = new byte[BUFSIZE];
58
+ }
59
+ public byte[] GetRecvDataList()
60
+ {
61
+ byte[] returnData;
62
+ lock (lockObj)
63
+ {
64
+ returnData = recvDataList[0];
65
+ recvDataList.RemoveAt(0);
66
+ }
67
+ return returnData;
68
+ }
65
69
 
66
- public BaseSocket() { }
70
+ public void AddRecvDateList(byte[] _data)
71
+ {
72
+ lock (lockObj)
73
+ {
74
+ recvDataList.Add(_data);
75
+ }
76
+ }
67
77
 
68
- ~BaseSocket() { Close(); }
69
-
70
- public void Init(string _ipAddr, int _port)
78
+ public int RecvDataListCount()
71
79
  {
72
- tcp = new System.Net.Sockets.TcpClient(_ipAddr, _port);
73
- //メッセージ
80
+ int count;
74
- Console.WriteLine("サーバー({0}:{1})と接続しました({2}:{3})。", ((System.Net.IPEndPoint)tcp.Client.RemoteEndPoint).Address,
75
- ((System.Net.IPEndPoint)tcp.Client.RemoteEndPoint).Port,
76
- ((System.Net.IPEndPoint)tcp.Client.LocalEndPoint).Address,
77
- ((System.Net.IPEndPoint)tcp.Client.LocalEndPoint).Port);
78
- //通信設定
81
+ lock (lockObj)
82
+ {
79
- ns = tcp.GetStream();
83
+ count= recvDataList.Count;
80
- ns.ReadTimeout = 10000;
84
+ }
81
- ns.WriteTimeout = 10000;
85
+ return count;
82
86
  }
83
87
 
88
+
84
- public void Send(byte[] _sendData, int _dataSize)
89
+ public int Send(byte[] _sendData, int _dataSize)
85
90
  {
91
+ int sendSize=-1;
92
+
86
93
  byte[] sendHeader;
87
94
 
88
95
  //header設定
@@ -92,91 +99,206 @@
92
99
  sendHeader.CopyTo(sendBytes, 0);
93
100
  _sendData.CopyTo(sendBytes, sendHeader.Length);
94
101
 
102
+ try
103
+ {
104
+ if (socket.Connected)
105
+ {
106
+ sendSize=socket.Send(sendBytes, sendBytes.Length, 0);
107
+ }
108
+ else
109
+ {
110
+ Console.WriteLine("sendError");
111
+ }
112
+ }
113
+ catch(System.ObjectDisposedException)
114
+ {
95
- //send
115
+ //閉じた時
116
+ /*
117
+ System.Console.WriteLine("閉じました。");
118
+ this.OnDeleteFlg();
119
+ */
120
+ }
121
+ catch (SocketException e)
122
+ {
96
- ns.Write(sendBytes, 0, sendBytes.Length);
123
+ Console.WriteLine("ソケットが切断されています。");
124
+ Console.WriteLine(e);
125
+ }
97
126
 
127
+ return sendSize;
98
128
  }
129
+
99
- public void Update()
130
+ public void OnDeleteFlg()
100
131
  {
101
- Routine();
132
+ lock (lockObj)
133
+ {
134
+ deleteFlg = true;
135
+ }
102
136
  }
103
- public void Close()
137
+ public void OnThreadDeleteFlg()
104
138
  {
139
+ lock (lockObj)
140
+ {
105
- deleteFlg = true;
141
+ deleteFlg = true;
106
- ns.Close();
142
+ }
107
- tcp.Close();
108
143
  }
109
144
 
145
+ }
146
+
147
+
148
+ class BaseServer
149
+ {
150
+ public List<TcpRecvServer> clientList { get;} = new List<TcpRecvServer>();
151
+ private List<TcpRecvServer> addClientList = new List<TcpRecvServer>();
152
+ private readonly object lockObj=new Object();
153
+ Socket listener;
154
+
155
+ public BaseServer() { }
156
+
157
+
110
- private void Routine()
158
+ public void BeginUpdate()
111
159
  {
160
+ //addClientListのための排他制御
112
- lock (lockObject)
161
+ lock (lockObj)
113
162
  {
114
- while (recvTempDataList.Count > sizeof(int))
163
+ if (addClientList.Count > 0)
115
164
  {
116
- int byteSize = (int)recvTempDataList[0];
117
- Console.WriteLine("Routine size={0}\n", byteSize);
118
- if (recvTempDataList.Count > byteSize+sizeof(int))
119
- {
120
- byte[] addData;
121
- addData = recvTempDataList.GetRange(sizeof(int), byteSize).ToArray();
122
- recvDataList.Add(addData);
165
+ clientList.AddRange(addClientList);
123
- recvTempDataList.RemoveRange(0, sizeof(int) + byteSize);
166
+ addClientList = new List<TcpRecvServer>();
124
- }
125
- else
126
- {
127
- return;
128
- }
129
167
  }
130
168
  }
131
169
  }
132
170
 
133
- public void Recv()
171
+ public void EndUpdate()
134
172
  {
135
- while (true)
173
+ if (clientList.Count <= 0) return;
174
+
175
+ List<TcpRecvServer> deleteList = new List<TcpRecvServer>();
176
+ foreach (TcpRecvServer client in clientList)
136
177
  {
137
- if (deleteFlg) { break; }
178
+ if (client.deleteFlg == true)
138
- byte[] resBytes = new byte[1024];
139
- int resSize = -1;
140
- resSize = ns.Read(resBytes, 0, resBytes.Length);
141
- if (resSize == 0)
142
179
  {
143
- Console.WriteLine("サーバーが切断しました。");
144
- deleteFlg = true;
180
+ deleteList.Add(client);
145
181
  }
182
+ }
183
+ foreach (TcpRecvServer client in deleteList)
184
+ {
146
- else if (resSize > 0)
185
+ clientList.Remove(client);
186
+ }
187
+ }
188
+ public void Init(string _ip, int _port)
189
+ {
190
+ //ListenするIPアドレス
191
+ IPAddress ipAdd = IPAddress.Parse(_ip);
192
+
193
+ //TcpListenerオブジェクトを作成する
194
+ IPEndPoint ipe = new IPEndPoint(ipAdd, _port);
195
+ listener = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
196
+ listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
197
+ listener.Bind(ipe);
198
+ listener.Listen(1000);
199
+
200
+ }
201
+
202
+ public async Task StartAccept()
203
+ {
204
+ await Task.Run(() =>
205
+ {
206
+ while (true)
147
207
  {
148
- Array.Resize(ref resBytes, resSize);
208
+ TcpRecvServer temp =new TcpRecvServer(listener.Accept());
149
- lock (lockObject)
209
+ lock (lockObj)
150
210
  {
151
- recvTempDataList.AddRange(resBytes);
211
+ addClientList.Add(temp);
212
+ Console.WriteLine("接続あり");
152
213
  }
153
- Console.WriteLine("recvSize={0},recvDataListSize={1}\n", resSize, recvTempDataList.Count);
214
+ StartReceive(temp);
154
215
  }
155
- }
216
+ });
156
217
  }
157
218
 
219
+
220
+ //===========================================================================
221
+ //recv関係
222
+ //===========================================================================
223
+ //データ受信スタート
158
- public int RecvDataSize()
224
+ private static void StartReceive(TcpRecvServer _server)
159
225
  {
226
+ //非同期受信を開始
227
+ _server.socket.BeginReceive(_server.ReceiveBuffer,
228
+ 0,
160
- return recvDataList.Count;
229
+ _server.ReceiveBuffer.Length,
230
+ System.Net.Sockets.SocketFlags.None,
231
+ new System.AsyncCallback(ReceiveDataCallback),
232
+ _server);
161
233
  }
162
234
 
235
+
163
- public async void StartRecvThread()
236
+ //BeginReceiveのコールバック
237
+ private static void ReceiveDataCallback(System.IAsyncResult ar)
164
238
  {
239
+ //状態オブジェクトの取得
240
+ TcpRecvServer server = (TcpRecvServer)ar.AsyncState;
241
+
242
+ //読み込んだ長さを取得
165
- await Task.Run(() =>
243
+ int len = 0;
244
+ try
166
245
  {
246
+ if(server.socket.Connected)len = server.socket.EndReceive(ar);
247
+ }
248
+ catch (System.ObjectDisposedException)
249
+ {
250
+ //閉じた時
251
+ System.Console.WriteLine("閉じました。");
252
+ server.OnDeleteFlg();
253
+ return;
254
+ }
255
+
256
+ //切断されたか調べる
257
+ if (len <= 0)
258
+ {
259
+ System.Console.WriteLine("切断されました。");
260
+ server.socket.Close();
261
+ server.OnDeleteFlg();
262
+ return;
263
+ }
264
+
265
+ //受信したデータを蓄積する
266
+ Array.Resize(ref server.ReceiveBuffer, len);
267
+ server.recvTempDataList.AddRange(server.ReceiveBuffer);
268
+
269
+ //受信用配列のサイズを元に戻す
270
+ Array.Resize(ref server.ReceiveBuffer, TcpRecvServer.BUFSIZE);
271
+
272
+ //データの整形
273
+ while (server.recvTempDataList.Count>sizeof(int))
274
+ {
275
+ int byteSize = (int)server.recvTempDataList[0];
276
+ if (server.recvTempDataList.Count > byteSize+sizeof(int))
277
+ {
278
+ byte[] addData;
279
+ addData = server.recvTempDataList.GetRange(sizeof(int), byteSize).ToArray();
280
+ server.AddRecvDateList(addData);
281
+ server.recvTempDataList.RemoveRange(0, sizeof(int) + byteSize);
282
+ }
283
+ else
284
+ {
285
+ break;
286
+ }
287
+ }
288
+
289
+ //再び受信開始
290
+ if(server.socket.Connected)server.socket.BeginReceive(server.ReceiveBuffer,
291
+ 0,
292
+ server.ReceiveBuffer.Length,
293
+ System.Net.Sockets.SocketFlags.None,
294
+ new System.AsyncCallback(ReceiveDataCallback),
167
- this.Recv();
295
+ server);
168
- });
169
296
  }
170
297
 
171
- public byte[] GetRecvData()
172
- {
173
- byte[] returnData;
174
- returnData = recvDataList[0];
175
- recvDataList.RemoveAt(0);
176
- return returnData;
177
- }
178
298
  }
179
299
 
300
+
301
+
180
302
  ```
181
303
  ### 実装環境
182
304
  mac