65.9K
CodeProject 正在变化。 阅读更多。
Home

Socket_Control DLL 资源和教程

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2013 年 4 月 1 日

CPOL

7分钟阅读

viewsIcon

26334

downloadIcon

176

一个 DLL 资源,旨在帮助初学者到中级开发人员在 P2P 应用程序中打开和使用套接字。

引言

本文档分发了一个 DLL 资源,用于帮助开发人员处理套接字和 P2P 应用程序,并让他们了解 DLL 中的类和函数。此 DLL 的目的是简化与 TCP 连接的接口以及端口的打开/使用。

背景

这不是一个关于如何在你的特定语言中使用 DLL 的教程,而是一个关于 Socket_Control.DLL 的参考和分发。如果你想学习如何导入和使用 DLL,请在本网站上查找大量的教程。

使用代码

要首先使用此 DLL,你必须在你自己的代码中将其中一个类定义为一个对象。此 DLL 包含两个类:

Client_Socket()
Server_Socket()

接下来需要设置一些属性

对于服务器来说,有:

  • Port 设置服务器将要监听的端口(默认 55433)
  • MaxClients 设置一次最多能加入的客户端数量(默认 25)

对于客户端,我们有:

  • IP 设置服务器所在的 IP 地址(默认 127.0.0.1)
  • Port 设置客户端将要连接的端口(默认 55433)

现在,为客户端调用 Connect() 函数,或为服务器调用 Start() 函数来初始化其余的对象,然后再调用任何其他函数。

Server_Socket() 的所有属性、事件和函数

名称 类型 描述
端口 属性 设置服务器将要监听的端口(默认 55433)
MaxClients 属性 设置一次可以连接的客户端数量(默认 25)
ConnectionEstablished(int ID) 事件 当新客户端连接时调用,并返回客户端的 ID
ClientDisconnect(int ID) 事件 当客户端断开连接时调用,并返回客户端 ID
Start() 函数 开始监听分配给 Port 属性的端口
objInit(int ClientID) 只读属性 以整数客户端 ID 作为输入,如果该客户端 ID 插槽中有客户端,则返回 true
Increment() 函数 MaxClients 属性加一
Terminate(int ClientID) 函数 终止与客户端的连接
Stream(int ClientID) 只读属性 返回客户端的数据流(如果可用),否则返回字符串 "%False%"
DataSend(String data, int ID) 函数 data 发送给客户端 ID

Client_Socket() 的所有属性、事件和函数

名称 类型 描述
IP 属性 设置服务器所在的 IP 地址(默认 127.0.0.1)
端口 属性 设置客户端将要连接的端口(默认 55433)
Connected() 只读属性 如果连接到服务器,则返回 true
Connect() 函数 连接到服务器 IP:Port
Stream() 只读属性 返回客户端的数据流(如果可用),否则返回字符串 "%False%"
DataSend(String data, int ID) 函数 data 发送给客户端 ID
Close() 函数

断开与服务器的连接,并取消初始化套接字,直到下次连接

示例(VB.NET)

服务器(控制台应用程序)

Imports System.Text.RegularExpressions

Module Module1
    Dim WithEvents Socket As New Socket_Control.Server_Socket
    Dim inStream As New Threading.Thread(AddressOf Streaming)

    Sub Main()
        msg("Max Client Slots:")
        Console.Write(" >> ")
        Dim max As String = Console.ReadLine()
        msg("Port: ")
        Console.Write(" >> ")
        Dim port As String = Console.ReadLine()
        Socket.MaxSlots = max
        Socket.Port = port
        Socket.Start()
        msg("Now Monitoring Port: " & Socket.Port)
        inStream.Start()
        While True

        End While
    End Sub

    Private Sub Streaming()
        While True
            Dim Count As Integer = 0
            While Not Count = Socket.MaxSlots
                Dim Stream As String = Socket.Stream(Count)
                If Not Stream = "%False%" Then
                    Dim Parsed() As String = Regex.Split(Stream, " ")
                    If Parsed(1) = "/close" Then
                        Socket.DataSend("%Closed%", Count)
                        Socket.Terminate(Count)
                        GoTo skip
                    End If
                    msg("[CLIENT " & Count + 1 & "] " & Stream)
                    Dim ID As Integer = 0
                    While Not ID = Socket.MaxSlots
                        If Not ID = Count AndAlso Socket.objInit(ID) Then
                            Socket.DataSend(Stream, ID)
                        End If
                        ID += 1
                    End While
skip:
                End If
                Count += 1
            End While
        End While
    End Sub

    Private Sub connectionEstablished(ByVal ID As String) Handles Socket.ConnectionEstablished
        msg("CLIENT " & ID + 1 & " Connected")
    End Sub

    Private Sub clientDisconnect(ByVal ID As String) Handles Socket.ClientDisconnect
        msg("CLIENT " & ID + 1 & " Disconnected")
    End Sub

    Private Sub msg(ByVal Message As String)
        Console.WriteLine(" >> " & Message)
    End Sub
End Module

首先,我们导入 System.Text.RegularExpressions,稍后将用于解析数据。

然后我们定义一些变量。

  • Socket - 这是我们 Socket_Control.Server_Socket 的实例,我们使用 WithEvents 声明它,以便稍后可以处理它引发的事件。
  • inStream - 这是一个新的线程,我们定义它来监控进出服务器的数据。我们将执行子程序分配给 Streaming()

现在来到我们的主子程序。首先,我们询问用户他们希望同时连接的最大客户端数量,并将他们的输入分配给一个名为 max 的变量。然后,我们询问他们希望服务器监听的端口,并将其分配给一个名为 port 的变量。然后,我们将 MaxClientsPort 属性分别分配给 maxport,然后启动服务器。

你可能已经注意到我之前使用了名为 msg() 的子程序。该子程序的原始内容在上面,但我也会将其放在下面

Private Sub msg(ByVal Message As String)
    Console.WriteLine(" >

在这里,我们再次使用该子程序来告诉用户服务器已启动,然后我们启动之前创建的线程的执行,然后设置一个无限循环,以使程序在线程执行时保持运行。

现在我们来到了我们的线程。首先,我们创建一个无限循环,以便我们的代码块会重复执行,直到程序结束。然后,我们创建一个整数来监视我们的下一个 while 循环。然后,我们设置一个 while 循环,当整数计数不等于可用插槽的最大数量时执行此操作。我们这样做是因为我们希望它循环遍历所有数组值。数组从 0 开始,所以如果你想要 4 个数组插槽,你实际上需要将其设置为 3,因为可用插槽将是 0、1、2、3,共 4 个插槽。因此,客户端数组中的数组大小是 maxslots - 1。如果达到了 maxslots,则停止。

现在,我们将客户端流获取为字符串,客户端 ID 为 Count。在此之后,我们使用之前导入的正则表达式,以 'Space' 作为分隔符将流拆分到 Parsed() 数组中。如果数据不可用,Socket.Stream 将返回 "%False%",因此我们在此处进行检查。如果数据可用,它会进行检查,否则什么也不做。我已经将客户端设置为发送数据:"[nickname] data",所以我们需要获取数组中的第二个位置,因此我们计算 Parsed(1),因为请记住,数组从 0 开始。如果它等于 "/close",那么我们将向客户端发送 "%closed%" 来告知客户端连接已关闭,然后终止该客户端的连接。否则,它会将数据发送给其他客户端。为了实现这一点,我们设置了另一个整数来监视我们的下一个 while 循环,并像以前一样设置 while 循环。如果 ID 不是发送数据的客户端的 ID,则将数据发送给该客户端。

这里我们来到了处理程序。每当发生事件时,就会调用处理程序。这些处理程序会处理有人连接和断开连接的情况。每个事件处理程序都只是发送一条简单的消息。

客户端(Windows 窗体应用程序)

像上面一样设置窗体

所有内容都保留其默认名称,richtextbox 被设置为只读,文本内容如下

/connect <IP> <port> - Opens connection on <IP>:<port>
/close - Disconnects from current connection
/nick <nickname> - Sets your Nickname 

ToolStripStatusLabel1 中的文本是 "Not Connected",还有一个间隔为 100 的计时器,保持禁用状态。

代码

Imports System.Text.RegularExpressions

Public Class Form1
    Dim Socket As New Socket_Control.Client_Socket
    Dim Connected As Boolean = False
    Dim Stream As String
    Dim Prev As String = "/connect localhost 55433"
    Dim Cur As String = ""
    Dim Nick As String = "[Default]"

    Private Sub Connect(ByVal IP As String, port As Integer)
        Socket.IP = IP
        Socket.Port = port
        Try
            Socket.Connect()
            ToolStripStatusLabel1.Text = "Connected To: " & Socket.IP & ":" & Socket.Port
            msg("Connection Opened On: " & Socket.IP & ":" & Socket.Port)
            Connected = True
            Timer1.Enabled = True
        Catch ex As Exception
            If Not ex.Message = Nothing Then msg(ex.Message)
            GoTo Skip
        End Try
Skip:
    End Sub

    Private Sub msg(ByVal Message As String)
        RichTextBox1.HideSelection = False
        RichTextBox1.Text &= Environment.NewLine & " >> " & Message
        RichTextBox1.SelectionStart = RichTextBox1.TextLength
    End Sub

    Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
        Stream = Socket.Stream
        If Not Stream = "%False%" Then
            If Stream = "%Closed%" Then
                msg("Connection To '" & Socket.IP & ":" & Socket.Port & "' Terminated")
                Connected = False
                ToolStripStatusLabel1.Text = "Not Connected"
                Timer1.Enabled = False
                Socket.Close()
            Else
                msg(Stream)
                Beep()
            End If
        End If
        Stream = ""
    End Sub

    Private Sub Form1_FormClosing(sender As System.Object, _
                e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
        If Not Socket.Connected Then GoTo ender
        Try
            Socket.DataSend("[] /close")
        Catch ex As Exception
            GoTo ender
        End Try
        Do Until Connected = False
            Application.DoEvents()
        Loop
ender:
        Try
            Socket.Close()
        Catch ex As Exception

        End Try
    End Sub

    Private Sub TextBox2_KeyDown(sender As System.Object, e As System.Windows.Forms.KeyEventArgs) Handles TextBox2.KeyDown
        Dim Parsed() As String = Regex.Split(TextBox2.Text, " ")
        If e.KeyValue = Keys.Enter Then
            e.SuppressKeyPress = True
            Prev = TextBox2.Text
            Cur = ""
            If Parsed(0) = "/connect" Then
                If Connected Then
                    msg("Connection Already Open")
                    msg("type /close to disconnect")
                ElseIf Not Parsed.Length = 3 Then
                    msg("Usage: /connect <IP> <port>")
                Else
                    Connect(Parsed(1), Parsed(2))
                End If
            ElseIf Parsed(0) = "/nick" Then
                If Not Parsed.Length = 2 Then
                    msg("Usage: /nick <nickname>")
                Else
                    Dim mesg As String = ""
                    For Count As Integer = 1 To Parsed.Length - 1
                        If Not Count = Parsed.Length - 1 Then
                            mesg &= Parsed(Count) & " "
                        Else
                            mesg &= Parsed(Count)
                        End If
                    Next
                    msg("Nickname Changed To: " & mesg)
                    If Connected Then
                        Try
                            Socket.DataSend(Nick & " Changed Their Nickname: " & mesg)
                        Catch ex As Exception
                            Connected = False
                            ToolStripStatusLabel1.Text = "Not Connected"
                            Timer1.Enabled = False
                            Socket.Close()
                            msg("Connection closed by remote host")
                        End Try
                    End If
                    Nick = "[" & mesg & "]"
                End If
            ElseIf Connected = True Then
                Try
                    Socket.DataSend(Nick & " " & TextBox2.Text)
                    msg("[ME] " & TextBox2.Text)
                Catch ex As Exception
                    Connected = False
                    ToolStripStatusLabel1.Text = "Not Connected"
                    Timer1.Enabled = False
                    Socket.Close()
                    msg("Error: Connection closed by remote host")
                End Try
            Else
                    msg("Error: Not Connected")
            End If
Skip:
            TextBox2.Text = Nothing
        ElseIf e.KeyValue = Keys.Up AndAlso Not TextBox2.Text = Prev Then
            Cur = TextBox2.Text
            TextBox2.Text = Prev
        ElseIf e.KeyValue = Keys.Down AndAlso Not Cur = "" Then
            TextBox2.Text = Cur
        End If
    End Sub
End Class

再次,我们导入正则表达式以供以后进行数据解析。

再次,我们定义一些变量

  • Socket - 我们的 Socket_Control.Client_Socket 实例
  • Connected - 一个全局布尔值,默认为 false,用于告知应用程序它是否已连接到服务器。
  • Prev - 保存用户上次键入的内容,用于向上箭头调出上次输入的命令。
  • Cur - 保存用户在按下向上箭头之前的输入内容。
  • Nick - 保存用户的昵称

在这里,我们创建了一个名为 Connect(IP, port) 的子程序,它非常直接。它将 IPPort 属性分别分配给 IPport,然后尝试连接。如果成功,它会发送一条消息,将 Connected 设置为 True,并启动计时器。

我们来到一个简单的子程序(msg()),它的功能与另一个 msg 子程序相同,它将消息发送到界面,并在 richtextbox 中向下滚动。

这里是计时器的 Tick 事件处理程序。每次计时器 Tick 时,它都会检查流。如果流不等于 "%False%",则继续检查。如果等于 "%Closed%",则发送连接已终止的消息,禁用计时器,并关闭套接字。否则,它将流发送到界面,并发出蜂鸣声作为用户警报。

这里是窗体关闭事件。在这里,它尝试关闭套接字,以实现干净的退出。

在这个子程序(按键处理程序)中,它会检查按键是否为 Enter。如果是 Enter,它会检查所有命令,并发送流,就像服务器一样。如果按键是向上,它会将文本框的值保存到 cur,并将文本框的值设置为 prev。如果按键是向下,则执行相反的操作。

Release

注意
我需要你们的反馈,这样我才能发布更新。如果我不知道如何改进,它永远不会变得更好。

历史

  • 03/31/13:1.0.0.0 发布
  • 04/01/13:2.0.0.0 开始构建
  • 04/05/13:将流 I/O 组织到一个子类中
  • 04/06/13:添加了 GetStrring() 和 GetBytes() 函数 

源代码/协作

要与开发者协作项目或获取自己的源代码,请联系 croug@bimbots.tk。

© . All rights reserved.