質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

1回答

9099閲覧

[C#]ソケット通信プログラムの構築について

ryo_se

総合スコア68

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

2クリップ

投稿2016/06/21 13:51

編集2016/06/22 03:41

現在ソケット通信を使用したプログラムを作成しております。

http://note.chiebukuro.yahoo.co.jp/detail/n1656
上記Webサイトを参考にし、Socketクラスを用いてサーバーとクライアント間での通信を行う基本的なプログラムは作成しました。

ですが、カスタムをしていく上で下記の実現ができず困っております。

1、1つのサーバーに対し、複数のクライアントから接続を行えるようにしたい。
2、サーバーが電文受信待機状態(SocketクラスのReciveメソッド)になっている時に、受信を中断 or 停止させたい。(勿論再開も)
3、サーバと接続中のクライアントの通信が切断され、その後クライアントの通信状態が回復した時、サーバと再接続を試みたい。

コードの詳細はURL先を見ていただければと思いますが、
Reciveメソッドについて調べたところ、中断や停止が無い様に見受けられました。

またサーバ側の流れとして下記となっています。
①クライアントとの接続待機(Acceptメソッド)
②クライアントと接続確立後、電文受信待機(Reciveメソッド)

3に関しては、上記状態になった際に電文受信待機でブロッキングされていることから、再度接続待機が行えない状態になっているのだと思います。

3つの実現に対し、サンプルやご教示をいただければ幸いです。

【追記】
複数クライアントの接続について、下記サイトを参考にしてコーディングしてみました。
https://codezine.jp/article/detail/22

上記サイトのサンプルではクライアントと接続ができたら即座にクローズしていますが、
今回は接続中のままとしています。

ところが接続中の複数のクライアントを管理、電文を送信するために、接続したSocketインスタンスをListに入れて保存という形をとってみましたが、一定時間毎にListにSocketインスタンスが追加されていってしまいます。

そもそも複数のクライアントを管理する上で正しい方法がわからず、ご教示をいただきたいです。

private Socket ServerSocket = null; private System.Net.IPEndPoint EndPointHost = null; //エンドポイント private List<Socket> ConnectSocketArray = new List<Socket>(); public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { } //クライアントの接続待ちスタート private void StartAccept(System.Net.Sockets.Socket server) { //接続要求待機を開始する server.BeginAccept( new System.AsyncCallback(AcceptCallback), server); } //BeginAcceptのコールバック private void AcceptCallback(System.IAsyncResult ar) { //サーバーSocketの取得 System.Net.Sockets.Socket server = (System.Net.Sockets.Socket)ar.AsyncState; //接続要求を受け入れる System.Net.Sockets.Socket client = null; try { //クライアントSocketの取得 client = server.EndAccept(ar); } catch { System.Console.WriteLine("閉じました。"); return; } //クライアントが接続した時の処理をここに書く //ここでは文字列を送信して、すぐに閉じている client.Send(System.Text.Encoding.UTF8.GetBytes("こんにちは。")); //client.Shutdown(System.Net.Sockets.SocketShutdown.Both); //client.Close(); ConnectSocketArray.Add(client); foreach (Socket cl in ConnectSocketArray) { Console.WriteLine(cl.ToString()); } Console.WriteLine(ConnectSocketArray.Count()); //接続要求待機を再開する server.BeginAccept( new System.AsyncCallback(AcceptCallback), server); } private void button1_Click(object sender, EventArgs e) { // Socket の生成 ServerSocket = new Socket( AddressFamily.InterNetwork, // IP version 4 のアドレス SocketType.Stream, // 通信方式をバイトストリーム ProtocolType.Tcp); // プロトコルをTCP // EndPointHostがnullならば、ホストのIPアドレスとポート番号の指定 if (EndPointHost == null) { EndPointHost = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("127.0.0.1"), 10002); } // ローカル エンドポイント(IPアドレス等の情報)と関連付け ServerSocket.Bind(EndPointHost); // 電文取り出しの接続がまだ保留中におけるキューの最大長 ServerSocket.Listen(100); StartAccept(ServerSocket); Console.WriteLine("待機状態になりました"); } private void button2_Click(object sender, EventArgs e) { ServerSocket.Shutdown(SocketShutdown.Both); ServerSocket.Close(); ServerSocket= null; Console.WriteLine("待機状態終了しました"); } //テキストボックスの内容を送信する private void button3_Click(object sender, EventArgs e) { string data = textBox1.Text; foreach(Socket client in ConnectSocketArray){ client.Send(System.Text.Encoding.UTF8.GetBytes(data)); } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

コードを参考にするならば、
Nonsoft さん:通信ツール(RS232C TCP/IP UDP/IP)
ここで紹介されている、TCPサーバーのコードは、上手に拡張してあげると、
簡単に10~20のクライアント対応になります。

TCP 状態変化は、
TCP 状態遷移 などで、検索してみてください。

投稿2016/06/21 15:02

daive

総合スコア2028

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ryo_se

2016/06/22 03:43

http://homepage2.nifty.com/nonnon/SoftSample/CS.NET/SampleTcpIp.html 上記を見てみましたがうまくできませんでした・・。 また今回、クライアント側はコネクションを張ったら、電文を送信してもコネクションは切らず、指示があるまではコネクションを張りっぱなしの方針で実装したいと思っています。
daive

2016/06/22 06:08 編集

>上記を見てみましたがうまくできませんでした・・。 VS2010 / 2015 Professional C# で、 再現方法を確認してみますね。 >指示があるまではコネクションを張りっぱなしの方針で TCP はコネクションして、通信しますので、どちらかの要因で切断しなければ、 コネクションしたままです。
daive

2016/06/22 09:03 編集

Lisner サンプル http://homepage2.nifty.com/nonnon/SoftSample/CS.NET/SampleTcpIp.html ```C# private void button1_Click(object sender, EventArgs e) { // ソケット送信 Byte[] dat = System.Text.Encoding.GetEncoding("SHIFT-JIS").GetBytes("abcあいう"); objStm.Write(dat, 0, dat.GetLength(0));      //↑ここで拒否や、送信できないエラーになる場合は、     //ServerサンプルのLocal IP を指定している処で、      // IP-V4 形式のIPアドレスが取得出来て居ない可能性があります。 } ``` Server サンプル http://homepage2.nifty.com/nonnon/SoftSample/CS.NET/SampleTcpIpSvr.html ```C# IPAddress myIp = Dns.GetHostEntry("localhost").AddressList[0]; // ↑で、IP-V4 アドレスが取得出来て居ない可能性があります。 ↓下記の様に書換てみてください。 IPAddress myIp = IPAddress.Any; ``` IPAddress myIp に、設定可能なパラメータ例 myIp = IPAddress.IPv6Any; myIp = IPAddress.Any; myIp = IPAddress.Parse("192.168.1.12");  //自PCのIPアドレス192.168.1.12の場合 ’ USB-COM / TCP / UDP を使う上で避けて通れない機能に、 delegate があります。様々なサイトで説明が見つかると思います。 デリゲート http://ufcpp.net/study/csharp/sp_delegate.html
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問