2016-03-30 5 views
-1

私は、TCPソケットを介して自分のサーバーをリッスンするプログラムを作成しようとしています。たとえば、アイテムの価格を更新すると、TCPサーバーに接続されているすべてのクライアントにJSON文字列が送信されます。私のC#プログラムでは、実行時にこの新しいTCPソケットを維持し、新しいデータがあるときはいつでもソケットから読み取ります。TcpClientは、新しいデータが利用できるときはいつも読んでいません。

私の問題は、TcpClientが送信されている最初のラウンドを過ぎて読み取ることを拒否していることです。それはそれを読んで、それからただ完全に働くことを止める。コードは次のとおりです:

TcpClient _client; 
static int readBytesLength = 1024; 
Byte[] readBytes = new byte[readBytesLength]; 

private void initClientConnection() { 
    _client = new TcpClient(); 
    _client.BeginConnect(SERVER_IP, SERVER_PORT, new AsyncCallback(connectCallback), _client); 
} 

private void connectCallback(IAsyncResult result) { 
    if (_client.Connected) { 
     Console.WriteLine("Connected!"); 
     this.beginReading(); 
    } 
    else { 
     Console.WriteLine("Failed to connect, trying again!"); 
     this.initClientConnection(); 
    } 
} 


private void beginReading() { 
    readBytes = new byte[readBytesLength]; 
    _client.GetStream().BeginRead(readBytes, 0, readBytesLength, receiveCallback, _client.GetStream()); 
} 

private void receiveCallback(IAsyncResult result) { 
    Console.WriteLine("Read Callback!"); 
    if (_client.GetStream().CanRead) { 
     string response = Encoding.UTF8.GetString(readBytes); 
     Console.WriteLine("Stream got \n{0}", response); 
    } 
    this.beginReading(); 
} 

また、私は1つのバッチデータを受信し、受信を停止します。

Stream got 
-----Received----- 
{"status":"SUCCESS","message": "Log in confirmed (2)"} 
+0

私はコードがまったく動作するのに驚いています。 'EndConnect'と' EndRead'へのあなたの呼び出しはどこですか?あなたもループのようなものはありません。そのため、クライアントに読み込みを行うように指示するだけです。私はあなたがクラスの仕組みを完全に理解するために 'TcpClient'のドキュメントをもう少し調べる必要があると思います。 –

+0

私はMSDN上のサンプルからこれを取り除き(そして変更して)、' beginReading() ' - 'receiveCallback()' - > 'beginReading()' - > ...で十分です。また、私が非ブロッキングである必要があるので、 'while(true)'ループを通してそれを実行したくありませんでした。 「EndConnect」と「EndRead」についての記述はありませんでした。これに関してあなたが参照している記事が分かりますか? – Dilisqq

+0

私の悪い、私は 'receiveCallback'の終わりに' beginReading'の呼び出しを逃しました。それでも、どのような例を使用しましたか? 'End 'は 'Begin 'の不可欠なパートナーです。たとえば、[BeginConnect'のMSDNページ](https://msdn.microsoft.com/en-us/library/ms145193%28v=vs.110%29.aspx)には、「EndConnect」を備考セクション –

答えて

1

コードではまだまだ奇妙なことがあります。 Stream.CanReadを使用する理由はなく、正しいオーバーロードはEncoding.GetStringではありません。私は少しあなたの例をきれいにし、いくつかの奇妙な/不必要なビットを修正しました。

using System; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 

public class TcpConnection 
{ 
    private const int BUF_SIZE = 1024; 
    private readonly byte[] buffer = new byte[BUF_SIZE]; 
    private readonly TcpClient client = new TcpClient(); 

    public void Start(IPAddress ip, int port) 
    { 
     client.BeginConnect(ip, port, ConnectCallback, null); 
    } 

    private void ConnectCallback(IAsyncResult result) 
    { 
     client.EndConnect(result); 
     Console.WriteLine("Connected!"); 
    } 

    private void StartRead() 
    { 
     if(!client.Connected) 
     { 
      Console.WriteLine("Disconnected, can't read."); 
      return; 
     } 
     NetworkStream stream = client.GetStream(); 
     stream.BeginRead(buffer, 0, BUF_SIZE, ReadCallback, stream);   
    } 

    private void ReadCallback(IAsyncResult result) 
    { 
     NetworkStream stream = (NetworkStream)result.AsyncState; 
     int bytesRead = stream.EndRead(result); 
     Console.WriteLine("Read Callback!"); 
     if (bytesRead > 0) 
     { 
      string response = Encoding.UTF8.GetString(buffer, 0, bytesRead); 
      Console.WriteLine("Stream got \n{0}", response); 
     } 
     StartRead(); 
    } 
} 
関連する問題