2009年06月05日(金)

C# ソケット通信の基礎

テーマ:C#


あちこちのサイトを参考にしてソケット通信を試してみた。

多分これが基本となるもの


--------------------------------------------------------------

サーバ側 : 受信する側のプログラム


<大体の手順>

  1)開くポートと使うIPアドレスを指定

  2)接続を待機するクラスにIPアドレスとポートを渡しサーバの登録

  3)サーバの開始

  4)接続があったらクライアントの取得

  5)データを取得するためのストリームを定義(事前にやっていてもOK)

  6)データを格納するbyteの配列を定義(事前にやっていてもOK)

  7)データの読み込み

  8)サーバの終了

--------------------------------------------------------------

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;  
//System.Netの参照設定が必要です


class Program

{

  static void Main(string[] args)
  {
    Console.WriteLine("キーを押下でサーバの開始");

    Console.ReadLine();


    try
    {
      //このプログラムが使用するポート番号と自身のIPアドレスを指定
      //IPアドレスはIPAddressという型で宣言
      int port = 2222;
      IPAddress ip = IPAddress.Parse("192.168.24.78");


      //クライアントからの接続を待機するサーバクラス設定
      TcpListener server = new TcpListener(ip, port);
      //サーバの開始 クライアントから接続されるまで待機
      server.Start();


      //接続があったらクライアント取得
      TcpClient client = server.AcceptTcpClient();


      //ついでにクライアントのIPアドレスを取得(無くても可)
      IPEndPoint endpoint = (IPEndPoint)client.Client.RemoteEndPoint;
      IPAddress address = endpoint.Address;


      //データをストリームへ取得
      NetworkStream stream = client.GetStream();


      //データを受け取るbyte型変数を定義(例では1バイトずつ受け取る)
      byte[] getData = new byte[1];


      //データの取得と同時に、取得したデータのバイト数も得る
      //引数は(受け皿,格納開始位置,受け取るバイト数)

      int cnt;

      //どれだけもらうかわからないので一時的に格納するリストを定義

      List<byte> bytelist=new List<byte>();

      //cntには受け取ったデータの長さが入る

      while((cnt = stream.Read(getData, 0, getData.length)) > 0)

      {

         //データをリストに追加していく

         bytelist.Add(getData);
      }


      //リストに入った分だけ配列を定義

      byte[] result = new byte[bytelist.Count];


      for(int i = 0 ; i < result.Length ; i++){

         result[i] = bytelist[i];

      }

      //文字列にエンコード

      string data = Encoding.UTF8.GetString(result);
      //データの出力
      Console.WriteLine("受信結果:{0}", data);


      //サーバの終了
      client.Close();


    }
    catch (Exception e)
    {
      Console.WriteLine(e.Message);
    }
    finally
    {
      Console.WriteLine("キーを押下で終了");
      Console.ReadLine();
    }
  }
}



--------------------------------------------------------------

クライアント側 : 送信する側のプログラム


<大体の手順>

  1)接続先のIPアドレスとポートを設定

  2)クライアント接続するクラスに、接続先のポートとIPアドレスを渡して登録

  3)送りたいデータをbyteの配列に格納(事前にやっていてもOK)

  4)データを送るためのストリームを作成(事前にやっていてもOK)

  5)データの送信

  6)接続先との接続を終了する

--------------------------------------------------------------

using System;
using System.Text;
using System.Net.Sockets;  
//System.Netの参照設定が必要です


class Program
{
  static void Main(string[] args)
  {
    Console.WriteLine("キーを押下で送信処理開始");
    Console.WriteLine("サーバ側が既に待機していることが条件です");
    Console.ReadLine();


    try
    {
      //IPアドレスとポート番号を指定
      //string型とint型なのが不思議
      //勿論送信先のIPアドレスとポート番号です

      string ipAddress = "221.250.82.146";
      int port = 2222;


      //IPアドレスとポート番号を渡してサーバ側へ接続
      TcpClient client = new TcpClient(ipAddress, port);


      //表示するのは「Hello! C#」
      //これを送信用にbyte型へ直します

      string str = "Hello! C#";
      byte[] tmp = Encoding.UTF8.GetBytes(str);


      //NWのデータを扱うストリームを作成
      NetworkStream stream = client.GetStream();


      //送信
      //引数は(データ , データ書き込み開始位置 , 書き込むバイト数)
      //だそうです

      stream.Write(tmp, 0, tmp.Length);


      //サーバとの接続を終了
      client.Close();

    }
    catch (Exception e)
    {
      Console.WriteLine(e.Message);
    }
    finally
    {
      Console.WriteLine("キーを押下で終了");
      Console.ReadLine();
    }
  }
}


--------------------------------------------------------------

上のコードをコピーして使用する場合

IPアドレスはサーバプログラムの実行環境で使用しているIPアドレスに

ポート番号は1024~65535の好きな数字に変えてください

--------------------------------------------------------------


使用クラスはここあたりを参考に

http://msdn.microsoft.com/ja-jp/library/system.net.sockets.aspx


TcpClient
  TCP ネットワーク サービスのためのクライアント接続を提供

NetworkStream
  ネットワーク アクセス用の基になるデータのストリームを提供

TcpListener
  TCP ネットワーク クライアントからの接続を待機



コメントはこれくらい丁寧に書かないとあとで自分がわからなくなるので

かなり事細かにかいてみました。

どこか解釈など間違っていましたらお知らせ願います。


大体の手順を洗い出してみると、サーバのほうがやることが多いですね

まあ、サーバの開始とクライアント取得だけですけど。



送受信を行うプログラムの場合は普通どうしているのだろうか

送信受信処理の度に毎回接続しなおしですかね?

他の人の意見をきく機会が無いのでいまいちわからないです。


あと、気になるのが実行時にいちいちファイアウォールに引っかかること。

これの改善方法ってどうしてるんだろう。



コメント

[コメントをする]

コメント投稿

一緒にプレゼントも贈ろう!

Amebaおすすめキーワード

    アメーバID登録して、ブログをつくろう! powered by Ameba (アメーバ)|ブログを中心とした登録無料サイト