📄 talker.vb
字号:
Imports System
Imports System.IO
Imports System.Net
Imports System.Text
Imports System.Threading
Imports System.Net.Sockets
Imports System.Windows.Forms
Class Talker
Implements IDisposable
'实现接口
Public socket As socket
'定义Socket
Public reader As TextReader
'定义读出流
Public writer As TextWriter
'定义写入流
Public client As Boolean
'标识程序是客户端还是服务器端
Public endPoint As IPEndPoint
'IP地址
Public prevSendText As String
'在此之前发出去的信息
Public prevReceiveText As String
'在此之前收到的信息
Public statusText As String
'连接状态
Public statusObj As Status
'定义Status类型变量
Public Sub Dispose() Implements IDisposable.Dispose
GC.SuppressFinalize(Me)
If Not (reader Is Nothing) Then
'这部分代码用来释放资源,销毁对象
reader.Close()
reader = Nothing
'释放读出流对象
End If
If Not (writer Is Nothing) Then
writer.Close()
'释放写入流对象
writer = Nothing
End If
If Not (socket Is Nothing) Then
socket.Close()
'释放Socket对象
socket = Nothing
End If
End Sub
Public Sub New(ByVal endPoint As IPEndPoint, ByVal client As Boolean)
'构造函数
Me.endPoint = endPoint
Me.client = client
socket = Nothing
reader = Nothing
writer = Nothing
statusText = String.Empty
prevSendText = String.Empty
prevReceiveText = String.Empty
End Sub
Protected Overrides Sub Finalize()
'析构
Dispose()
MyBase.Finalize()
End Sub
Friend Event Notifications(ByVal notify As Notification, ByVal data As Object)
'定义【通知】事件,对notify进行处理
Public Enum Notification
'系统可能的通知
Initialized = 1
StatusChange
ReceivedAppend
ReceivedRefresh
EndNotify
ErrorNotify
End Enum
Public Enum Status
'状态
侦听
已正常连接
End Enum
Public Sub Start()
ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback _
(AddressOf EstablishSocket))
'将用户项排队到线程池,调用指定的委托,
'并指定在接受线程池服务时要传递给委托的对象()
End Sub
Private Sub EstablishSocket(ByVal state As Object)
Dim stream As NetworkStream
'定义流
stream = Nothing
'初始化
Try
If Not client Then
'如果不是客户端,则进行侦听
Dim listener As Socket
Try
listener = New Socket(AddressFamily.InterNetwork, _
SocketType.Stream, ProtocolType.Tcp)
'实例化Socket类
listener.Blocking = True
'指示Socket处于阻塞模式
listener.Bind(endPoint)
'绑定本地的IP地址
SetStatus(Status.侦听)
'显示状态
listener.Listen(0)
'侦听
socket = listener.Accept()
'处理传入的连接请求
listener.Close()
'关闭Socket连接
stream = New NetworkStream(socket)
'实例化流类
reader = New StreamReader(stream)
'实例化读出流类
writer = New StreamWriter(stream)
'实例化写入流类
writer.Write("WINTALK .NET")
writer.Flush()
'清理缓冲区,将所有的缓冲数据写入基础设备
Catch e As SocketException
'如果已经存在了一个侦听端,那么这个端口作为客户端
If e.ErrorCode = 10048 Then
client = True
endPoint = New IPEndPoint _
(Dns.Resolve("127.0.0.1").AddressList(0), endPoint.Port)
'设置端口地址
Else
RaiseEvent Notifications _
(Notification.ErrorNotify, "初始化Socket时发生错误:" & ControlChars.CrLf & e.ToString())
'触发事件
End If
End Try
End If
If client Then '以客户端形式进行连接
Dim temp As New Socket(AddressFamily.InterNetwork, _
SocketType.Stream, ProtocolType.Tcp)
'实例化Socket类
temp.Blocking = True
'指示Socket处于阻塞模式
temp.Connect(endPoint)
socket = temp
socket.SetSocketOption(SocketOptionLevel.Socket, _
SocketOptionName.ReceiveTimeout, 5000)
socket.SetSocketOption(SocketOptionLevel.Socket, _
SocketOptionName.SendTimeout, 5000)
stream = New NetworkStream(socket)
reader = New StreamReader(stream)
writer = New StreamWriter(stream)
Dim handshake(11) As Char
'判断是否连接上,通过发出的 WINTALK .NET 消息来判断
Try
If Not (reader.Read(handshake, 0, 12) > 0 And New _
String(handshake) = "WINTALK .NET") Then
socket.Close()
socket = Nothing
Else
socket.SetSocketOption(SocketOptionLevel.Socket, _
SocketOptionName.ReceiveTimeout, 0)
socket.SetSocketOption(SocketOptionLevel.Socket, _
SocketOptionName.SendTimeout, 0)
End If
Catch
socket.Close()
socket = Nothing
End Try
End If
If Not (socket Is Nothing) Then
SetStatus(Status.已正常连接)
RaiseEvent Notifications(Notification.Initialized, Me)
'触发事件进行初始化
ReceiveTalk() '开始收取信息
RaiseEvent Notifications(Notification.EndNotify, "远程连接已经关闭")
Else
RaiseEvent Notifications(Notification.ErrorNotify, _
"建立Socket失败,检查端口设置是否正确")
End If
Catch e As IOException
Dim sockExcept As SocketException = _
CType(e.InnerException, SocketException)
If Not (sockExcept Is Nothing) And 10054 = sockExcept.ErrorCode Then
RaiseEvent Notifications(Notification.EndNotify, "远程连接已经断开")
Else
RaiseEvent Notifications(Notification.ErrorNotify, "Socket 错误" & _
ControlChars.CrLf & e.Message)
End If
Catch e As Exception
RaiseEvent Notifications(Notification.ErrorNotify, "Socket 错误" & _
ControlChars.CrLf & e.Message)
End Try
End Sub
Public Sub SendTalk(ByVal newText As String)
'向远程机器发送信息
Dim send As String
If prevSendText.Length <= newText.Length And _
String.CompareOrdinal(newText, 0, prevSendText, 0, _
prevSendText.Length) = 0 Then
'判断是否是附加的字符串
Dim append As [String] = newText.Substring(prevSendText.Length)
send = String.Format("A{0}:{1}", append.Length, append)
Else
send = String.Format("R{0}:{1}", newText.Length, newText)
'否则取代该字符串
End If '
writer.Write(send)
'发送字符串
writer.Flush()
'清理缓冲区
prevSendText = newText
'保存字符串为后面作比较
End Sub
Private Sub SetStatus(ByVal statusObj As Status)
Me.statusObj = statusObj
'获取系统状态
RaiseEvent Notifications(Notification.StatusChange, statusObj)
'设置状态
End Sub
Private Sub ReceiveTalk()
'从远程客户端获取信息
Dim commandBuffer(19) As Char
Dim oneBuffer(0) As Char
Dim readMode As Integer = 1
Dim counter As Integer = 0
Dim textObj As New StringBuilder()
While readMode <> 0
If reader.Read(oneBuffer, 0, 1) = 0 Then
readMode = 0
Else
Select Case readMode
Case 1
If counter = commandBuffer.Length Then
readMode = 0
End If
If oneBuffer(0) <> ":"c Then
commandBuffer(counter) = oneBuffer(0)
counter = counter + 1
Else
counter = Convert.ToInt32(New String(commandBuffer, 1, _
counter - 1))
If counter > 0 Then
readMode = 2
textObj.Length = 0
Else
If commandBuffer(0) = "R"c Then
counter = 0
prevReceiveText = String.Empty
RaiseEvent Notifications _
(Notification.ReceivedRefresh, prevReceiveText)
End If
End If
End If
Case 2
textObj.Append(oneBuffer(0))
counter = counter - 1
If counter = 0 Then
Select Case commandBuffer(0)
Case "R"c
prevReceiveText = textObj.ToString()
RaiseEvent Notifications _
(Notification.ReceivedRefresh, prevReceiveText)
Case Else
Dim newText As String
newText = textObj.ToString()
prevReceiveText += newText
RaiseEvent Notifications _
(Notification.ReceivedAppend, newText)
End Select
readMode = 1
End If
Case Else
readMode = 0
End Select
End If
End While
End Sub
End Class
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -