我正在尝试创建一个简单的游戏,需要一个TcpConnection。
所以我创建了一个Server类,它包装了TcpListener,与Client和TcpClient一样。但是当我附加Listener Sub并发送消息时它只会在第一个上被调用:
服务器Imports System.Net.Sockets
Public Class Server
Inherits ConnectionPartner
Private Server As TcpListener
Private Client As TcpClient
Private Stream As NetworkStream
Private Port As Integer
Public Sub Init(ByVal port As Integer)
Server = New TcpListener(port)
End Sub
Public Sub Open()
Server.Start()
Client = Server.AcceptTcpClient()
Stream = Client.GetStream()
End Sub
Public Overrides Sub Write(ByVal Message As String)
Dim Bytes() As Byte = Encoder.GetBytes(Message)
Me.Write(Bytes)
End Sub
Public Overrides Sub Write(ByVal Message() As Byte)
If Stream Is Nothing Then Return
Stream.Write(Message, 0, Message.Length)
End Sub
Public Overrides Sub Listen(ByVal Handler As Action(Of String))
Listen(Sub(ByVal Message() As Byte)
Handler(Encoder.GetString(Message))
End Sub)
End Sub
Public Overrides Sub Listen(ByRef Handler As Action(Of Byte()))
Dim Buffer(Client.ReceiveBufferSize()) As Byte
While (True)
Utils.Log("Listening")
Client.GetStream().Read(Buffer, 0, Buffer.Length)
Handler(Buffer)
End While
End Sub
Public Sub Close()
Try
Client.Close()
Catch ex As Exception
End Try
Try
Server.Stop()
Catch ex As Exception
End Try
End Sub
End Class
客户Imports System.Net
Imports System.Net.Sockets
Public Class Client
Inherits ConnectionPartner
Private Socket As TcpClient
Private Stream As NetworkStream
Private Port As Integer
Public Sub Init()
Socket = New TcpClient()
End Sub
Public Sub Open(ByVal Ip As IPAddress, ByVal Port As Integer)
Socket.Connect(Ip, Port)
Stream = Socket.GetStream()
End Sub
Public Overrides Sub Write(ByVal Message As String)
Dim Bytes() As Byte = Encoder.GetBytes(Message)
Me.Write(Bytes)
End Sub
Public Overrides Sub Write(ByVal Message() As Byte)
If Stream Is Nothing Then Return
Stream.Write(Message, 0, Message.Length)
End Sub
Public Overrides Sub Listen(ByVal Handler As Action(Of String))
Listen(Sub(ByVal Message() As Byte)
Handler(Encoder.GetString(Message))
End Sub)
End Sub
Public Overrides Sub Listen(ByRef Handler As Action(Of Byte()))
Dim Buffer(Socket.ReceiveBufferSize()) As Byte
While (True)
Utils.Log("Listening")
Stream.Read(Buffer, 0, Buffer.Length)
Handler(Buffer)
End While
End Sub
Public Sub Close()
Try
Socket.Close()
Catch ex As Exception
End Try
End Sub
End Class
My Test Class
Imports System.Net
Imports System.Threading
Class MainWindow
Private Server As Server = New Server()
Private Client As Client = New Client()
Private C As Connection
Private Port As Integer = My.Resources.Port
Private Sub button_client_init_Click(sender As Object, e As RoutedEventArgs) Handles button_client_init.Click
Client.Init()
End Sub
Private Sub button_client_start_Click(sender As Object, e As RoutedEventArgs) Handles button_client_start.Click
Client.Open(Dns.GetHostEntry("localhost").AddressList(1), Port)
End Sub
Private Sub button_client_write_Click(sender As Object, e As RoutedEventArgs) Handles button_client_write.Click
Client.Write("bar")
End Sub
Private Sub button_client_listen_Click(sender As Object, e As RoutedEventArgs) Handles button_client_listen.Click
Dim T As Thread = New Thread(Sub()
Client.Listen(Sub(ByVal M As String)
Log("Client:" & M)
End Sub)
End Sub)
T.Start()
End Sub
Private Sub button_server_init_Click(sender As Object, e As RoutedEventArgs) Handles button_server_init.Click
Server.Init(Port)
End Sub
Private Sub button_server_start_Click(sender As Object, e As RoutedEventArgs) Handles button_server_start.Click
Dim T As Thread = New Thread(Sub()
Server.Open()
End Sub)
T.Start()
End Sub
Private Sub button_server_write_Click(sender As Object, e As RoutedEventArgs) Handles button_server_write.Click
Server.Write("foo")
End Sub
Private Sub button_server_listen_Click(sender As Object, e As RoutedEventArgs) Handles button_server_listen.Click
Dim T As Thread = New Thread(Sub()
Server.Listen(Sub(ByVal M As String)
Log("Server: " & M)
End Sub)
End Sub)
T.Start()
End Sub
End Class
编辑:
我尝试用StreamReader/Writers做整个事情。现在我甚至没有得到síngle消息:
服务器Imports System.IO
Imports System.Net.Sockets
Public Class Server
Inherits ConnectionPartner
Private Server As TcpListener
Private Client As TcpClient
Private Reader As StreamReader
Private Writer As StreamWriter
Private Port As Integer
Public Sub Init(ByVal port As Integer)
Server = New TcpListener(port)
End Sub
Public Sub Open()
Server.Start()
Client = Server.AcceptTcpClient()
Dim Stream As NetworkStream = Client.GetStream()
Reader = New StreamReader(Stream)
Writer = New StreamWriter(Stream)
End Sub
Public Overrides Sub Write(ByVal Message As String)
Writer.WriteLine(Message)
End Sub
Public Overrides Sub Write(ByVal Message() As Byte)
End Sub
Public Overrides Sub Listen(ByVal Handler As Action(Of String))
While True
Dim Message As String = Reader.ReadLine()
Handler(Message)
End While
End Sub
Public Overrides Sub Listen(ByRef Handler As Action(Of Byte()))
End Sub
Public Sub Close()
Try
Client.Close()
Catch ex As Exception
End Try
Try
Server.Stop()
Catch ex As Exception
End Try
End Sub
End Class
客户Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Public Class Client
Inherits ConnectionPartner
Private Socket As TcpClient
Private Reader As StreamReader
Private Writer As StreamWriter
Private Port As Integer
Public Sub Init()
Socket = New TcpClient()
End Sub
Public Sub Open(ByVal Ip As IPAddress, ByVal Port As Integer)
Socket.Connect(Ip, Port)
Dim Stream As NetworkStream = Socket.GetStream()
Reader = New StreamReader(Stream)
Writer = New StreamWriter(Stream)
End Sub
Public Overrides Sub Write(ByVal Message As String)
Writer.WriteLine(Message)
End Sub
Public Overrides Sub Write(ByVal Message() As Byte)
End Sub
Public Overrides Sub Listen(ByVal Handler As Action(Of String))
While True
Dim Message As String = Reader.ReadLine()
Handler(Message)
End While
End Sub
Public Overrides Sub Listen(ByRef Handler As Action(Of Byte()))
End Sub
Public Sub Close()
Try
Socket.Close()
Catch ex As Exception
End Try
End Sub
End Class
解决方案:
忘记冲洗消息。
服务器Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Public Class Server
Inherits ConnectionPartner
Private Server As TcpListener
Private Client As TcpClient
Private Reader As StreamReader
Private Writer As StreamWriter
Private Port As Integer
Public Sub Init(ByVal Ip As IPAddress, ByVal Port As Integer)
Server = New TcpListener(Ip, Port)
End Sub
Public Sub Open()
Server.Start()
Client = Server.AcceptTcpClient()
Dim Stream As NetworkStream = Client.GetStream()
Reader = New StreamReader(Stream)
Writer = New StreamWriter(Stream)
Writer.AutoFlush = True
End Sub
Public Overrides Sub Start(ByVal Ip As IPAddress, ByVal Port As Integer)
Me.Init(Ip, Port)
Me.Open()
End Sub
Public Overrides Sub Write(ByVal Message As String)
Writer.WriteLine(Message)
End Sub
Public Overrides Sub Listen(ByVal Handler As Action(Of String))
While True
Dim Message As String = Reader.ReadLine()
Handler(Message)
End While
End Sub
Public Overrides Sub Close()
Try
Client.Close()
Catch ex As Exception
End Try
Try
Server.Stop()
Catch ex As Exception
End Try
End Sub
End Class
客户Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Public Class Client
Inherits ConnectionPartner
Private Socket As TcpClient
Private Reader As StreamReader
Private Writer As StreamWriter
Private Port As Integer
Public Sub Init()
Socket = New TcpClient()
End Sub
Public Sub Open(ByVal Ip As IPAddress, ByVal Port As Integer)
Socket.Connect(Ip, Port)
Dim Stream As NetworkStream = Socket.GetStream()
Reader = New StreamReader(Stream)
Writer = New StreamWriter(Stream)
Writer.AutoFlush = True
End Sub
Public Overrides Sub Start(ByVal Ip As IPAddress, ByVal Port As Integer)
Me.Init()
Me.Open(Ip, Port)
End Sub
Public Overrides Sub Write(ByVal Message As String)
Writer.WriteLine(Message)
End Sub
Public Overrides Sub Listen(ByVal Handler As Action(Of String))
While True
Dim Message As String = Reader.ReadLine()
Handler(Message)
End While
End Sub
Public Overrides Sub Close()
Try
Socket.Close()
Catch ex As Exception
End Try
End Sub
End Class
TCP根本不提供消息。它提供无边界的字节流。当你使用Read
时,你可以得到任意字节数,低至1。您的代码需要假定任意分块。这里,您假设每次都得到一个完整的缓冲区。
您可以使用BinaryReader.ReadBytes
来读取精确的字节数。StreamReader/Writer
使基于文本的协议更容易。
ReceiveBufferSize
不是传入的字节数。它的值是没有意义的,不要看它