C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: VB.NET:Socketで非同期のTCP通信


(過去ログ 27 を表示中)

[トピック内 4 記事 (1 - 4 表示)]  << 0 >>

■12753 / inTopicNo.1)  VB.NET:Socketで非同期のTCP通信
  
□投稿者/ お化け (1回)-(2008/01/16(Wed) 23:04:41)

分類:[.NET 全般] 

はじめまして。VB.NETでSocketクラスを利用した通信アプリを作ることになりました。
作りとしては、差し当たりは練習でサーバーとクライアントを1対1で、受信は非同期、送信は同期でという感じです。
実際調べながら組んでみました。理屈を完全に分かったわけではないですが、なんとなくできました。

ただ、クライアント側の処理で、受信した文字列をフォームのテキストに表示させたいのですがうまくいきません。
非同期呼び出しではBeginInvokeを使うというところまでは分かったのですが、実際やってみても表示されません。

手探りで色々変な点もあるかと思うのですが、下にコードを書きます。

現在はサーバー側から1秒おきくらいにメッセージが送られてきます。txtというIDのTextBoxに文字を追加したいのですが、
txt.AppendText(文字)とやっても表示されません。
しかし例えばMsgBox( txt.Text )とやるとちゃんと追加した文字がメッセージボックスには表示されている感じです。なんかよくわかんないです。
txt.RefreshとかForm1.Refreshとかもやってみましたが駄目な感じです。

''----クライアント----
Imports System
Imports System.Net
Imports System.Net.Sockets
Imports System.IO
Imports System.Text
Imports System.Text.Encoding
Imports System.Threading
Imports System.Threading.Thread

Public Class Form1
Private Delegate Function OnConnectDelegate() As Boolean

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Public Class DoragonQuest
Public Sock As Socket ''汎用
Public SendSock As Socket ''送信用
Public IPEnd As IPEndPoint
Public Connected As Boolean = False
Private SockEvent As New ManualResetEvent(False)
Private Const CONNECT As String = "CONNECTION"
Public Sub New(ByVal host As String, ByVal port As String)
Me.Sock = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Me.IPEnd = New IPEndPoint(Dns.GetHostEntry(host).AddressList(0), port)
Me.SockEvent.Reset()
Me.Sock.BeginConnect(Me.IPEnd, New AsyncCallback(AddressOf ConnectCallback), Me.Sock)
Me.SockEvent.WaitOne()
End Sub

''こいつは非同期別スレッドで呼んで欲しい
Public Function OnConnection() As Boolean
Me.SendSock = Me.Sock
Me.SendMsg(DoragonQuest.CONNECT)
SockEvent.Set()
Dim Handler As Socket = Me.Sock
Dim State As New StateObject()
State.WorkSocket = Handler
SyncLock Me
Handler.BeginReceive(State.Buff, 0, StateObject.BuffSize, SocketFlags.None, New AsyncCallback(AddressOf ReceiveCallback), State)
End SyncLock
End Function

Private Sub ConnectCallback(ByVal ar As IAsyncResult)
Dim Client As Socket = CType(ar.AsyncState, Socket)
Client.EndConnect(ar)
Me.SockEvent.Set()
End Sub

Public Sub SendMsg(ByVal msg As String)
SyncLock Me
Me.SendSock.Send(Encoding.UTF8.GetBytes(msg))
Sleep(1)
End SyncLock
End Sub

Private Sub ReceiveCallback(ByVal ar As IAsyncResult)
Dim State As StateObject = CType(ar.AsyncState, StateObject)
Dim Handler As Socket = State.WorkSocket
Dim ReadSize As Integer
Try
ReadSize = Handler.EndReceive(ar)
Catch ex As Exception
Me.Connected = False
OnConnection()
End Try
If ReadSize < 1 Then
Return
End If
Dim Buffer(ReadSize) As Byte
Array.Copy(State.Buff, Buffer, ReadSize)
Me.SendSock = Handler
Me.Connected = True

Dim msg As String = Encoding.UTF8.GetString(Buffer)
''-------------------------------------------------------------------------------------
''ここが問題の場所です
Form1.txt.AppendText(msg)
''-------------------------------------------------------------------------------------
SyncLock Me
Handler.BeginReceive(State.Buff, 0, StateObject.BuffSize, SocketFlags.None, New AsyncCallback(AddressOf ReceiveCallback), State)
End SyncLock
End Sub
Private Class StateObject
Public WorkSocket As Socket
Public Const BuffSize As Integer = 1024
Public Buff(StateObject.BuffSize) As Byte
End Class

End Class

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim A As New DoragonQuest("localhost", 60001)
Dim del As New OnConnectDelegate(AddressOf A.OnConnection)
Dim result As IAsyncResult = del.BeginInvoke(Nothing, Nothing)
End Sub
End Class


''----サーバー----
Sub Main()
Dim A As New FinalFantasy("localhost", 60001)
Do
If A.Connected Then
A.SendMsg("もういやだ")
End If
Console.WriteLine("-------------------------------------------------------")
Sleep(1000)
Loop
Console.Read()
End Sub

Public Class FinalFantasy
Public Sock As Socket ''汎用
Public SendSock As Socket ''送信用
Public IPEnd As IPEndPoint
Public Connected As Boolean = False
Private SockEvent As New ManualResetEvent(False)

Public Sub New(ByVal host As String, ByVal port As String)
Me.Sock = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Me.IPEnd = New IPEndPoint(Dns.GetHostEntry(host).AddressList(0), port)
Me.Sock.Bind(Me.IPEnd)
Me.Sock.Listen(100)

Dim t As New Thread(New ThreadStart(AddressOf WaitConnection))
t.IsBackground = True
t.Start()
End Sub

Public Function WaitConnection() As Boolean
SockEvent.Reset()
Me.Sock.BeginAccept(New AsyncCallback(AddressOf OnConnection), Sock)
SockEvent.WaitOne()
End Function

Public Sub SendMsg(ByVal msg As String)
SyncLock Me
Me.SendSock.Send(Encoding.UTF8.GetBytes(msg))
Sleep(1)
End SyncLock
End Sub

Private Sub OnConnection(ByVal ar As IAsyncResult)
SockEvent.Set()
Dim Handler As Socket = Me.Sock.EndAccept(ar)
Dim State As New StateObject()
State.WorkSocket = Handler
SyncLock Me
Handler.BeginReceive(State.Buff, 0, StateObject.BuffSize, SocketFlags.None, New AsyncCallback(AddressOf ReceiveCallback), State)
End SyncLock
End Sub
Private Sub ReceiveCallback(ByVal ar As IAsyncResult)
Dim State As StateObject = CType(ar.AsyncState, StateObject)
Dim Handler As Socket = State.WorkSocket
Dim ReadSize As Integer
Try
ReadSize = Handler.EndReceive(ar)
Catch ex As Exception
Me.Connected = False
WaitConnection()
End Try
If ReadSize < 1 Then
Return
End If
Dim Buffer(ReadSize) As Byte
Array.Copy(State.Buff, Buffer, ReadSize)
Me.SendSock = Handler
Me.Connected = True

Dim msg As String = Encoding.UTF8.GetString(Buffer)
Console.WriteLine(msg)
SyncLock Me
Handler.BeginReceive(State.Buff, 0, StateObject.BuffSize, SocketFlags.None, New AsyncCallback(AddressOf ReceiveCallback), State)
End SyncLock
End Sub
Private Class StateObject
Public WorkSocket As Socket
Public Const BuffSize As Integer = 1024
Public Buff(StateObject.BuffSize) As Byte
End Class
End Class

何か原因があると思うのですが、分かりません。
お分かりになるようであれば教えてください。よろしくお願いします。
引用返信 編集キー/
■12754 / inTopicNo.2)  Re[1]: VB.NET:Socketで非同期のTCP通信
□投稿者/ 引っ込んだID非公開 (8回)-(2008/01/17(Thu) 01:19:50)
2008/01/17(Thu) 01:30:48 編集(投稿者)
2008/01/17(Thu) 01:29:34 編集(投稿者)

15回目の投稿です

 はじめまして、引っ込んだID非公開と申します。

 まだコードを詳しく読んでおりませんが、
 私のPCで動作させてみたところ、
 「問題の場所」でControl.Invokeを使用すると、
 文字列「もういやだ」がTextBoxに1秒毎に表示されました。
 現段階ではそこまでしか分かりません。

 # 私の推測で、違っていたら申し訳ないのですが、
 # VB2003以前のバージョンをお使いではないでしょうか?
 # VB2005以降の場合、デバックモードで実行するとエラー(InvalidOperationExceptionがスローされます)になるので・・・

 以上、取り急ぎご報告いたします。
 
 P.S.おやすみなさい

[追記]コードはそのままでは動作しませんでした。何箇所か単純ミスがありました。例:ByVal port As String

以上です。

引用返信 編集キー/
■12759 / inTopicNo.3)  Re[2]: VB.NET:Socketで非同期のTCP通信
□投稿者/ お化け (3回)-(2008/01/17(Thu) 09:56:42)
引っ込んだID非公開 さん

とても丁寧な対応ありがとうございます。

色々変なところがある感じで恥ずかしいです。色々お手間をおかけしまして、ごめんなさい。
環境ですが、自宅はVB2008で会社がVS2005です。今会社で動かしてみましたが、一応動きました(動作の違いは私がいつもOption Strict をOffにしてるから、とかそういう感じでしょうか?)。

というかTextBoxに表示されました?なんと、あれれれ?
さらに、エラーでますですか?あららら。

うーん、なんかわかんないので、整理して綺麗にするところからはじめてみます。
大変お手数おかけしました、感謝!

また何かあったらよろしくお願いします。


No12754 (引っ込んだID非公開 さん) に返信
> 2008/01/17(Thu) 01:30:48 編集(投稿者)
> 2008/01/17(Thu) 01:29:34 編集(投稿者)
>
> 15回目の投稿です
>
>  はじめまして、引っ込んだID非公開と申します。
>
>  まだコードを詳しく読んでおりませんが、
>  私のPCで動作させてみたところ、
>  「問題の場所」でControl.Invokeを使用すると、
>  文字列「もういやだ」がTextBoxに1秒毎に表示されました。
>  現段階ではそこまでしか分かりません。
>
>  # 私の推測で、違っていたら申し訳ないのですが、
>  # VB2003以前のバージョンをお使いではないでしょうか?
>  # VB2005以降の場合、デバックモードで実行するとエラー(InvalidOperationExceptionがスローされます)になるので・・・
>
>  以上、取り急ぎご報告いたします。
>  
>  P.S.おやすみなさい
>
> [追記]コードはそのままでは動作しませんでした。何箇所か単純ミスがありました。例:ByVal port As String
>
> 以上です。
>
引用返信 編集キー/
■12799 / inTopicNo.4)  Re[3]: VB.NET:Socketで非同期のTCP通信
□投稿者/ 倉田 有大 (118回)-(2008/01/17(Thu) 18:38:58)
http://codezine.jp/a/article.aspx?aid=144
http://codezine.jp/a/article/aid/22.aspx
このページは役に立ちませんか?
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -