|
分類:[.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
何か原因があると思うのですが、分かりません。 お分かりになるようであれば教えてください。よろしくお願いします。
|