.net中的socket异步通信实现--客户端代码

在上一篇文章中主要介绍了socket异步通信实现的服务器端代码,下面我们来分析一下客户端代码:
那么在设计客户端代码时我们主要考虑哪些问题呢?
第一是如何接收数据,往往一次传输的数据量较大,但socket一次的传输量是1024个byte,因此需要对数据在发送端进行拆分,而在接收端进行组合。
第二是需要建立缓冲区,网络传输的速度肯定比我们处理数据的速度快。
大家如果需要使用这段代码,需要编写一下其中的ClassSetup类,该类包含每个工作站的配置信息,由于版权问题,在这里就不公开了。
客户端代码如下:
Public   Class  ClassServer

#Region  "参数"

    
' 以下是客户端到服务器端的消息开头 
     Const  LOGININ  As   String   =   " 10 "   ' 请求登陆的消息|||消息形式:10+自己的用户名 
     Const  LOGINOUT  As   String   =   " 11 "   ' 请求登出的消息|||消息形式:11+自己的用户名 
     Const  GETULIST  As   String   =   " 12 "   ' 请求获得在线用户列表|||消息形式:12+自己的用户名 
     Const  P2PCONN  As   String   =   " 13 "   ' 请求P2P连接的消息|||消息形式:13+自己的用户名+对方的用户名 
     Const  HOLDLINE  As   String   =   " 14 "   ' 保持连接.|||消息开式:14+自己的用户名 

    
' 以下是服务器到客户端的消息开头 
     Const  HVUSER  As   String   =   " 20 "   ' 用户名已存在 
     Const  GETUSER  As   String   =   " 21 "   ' 在线用户列表|||消息格式:21+用户名+EP 
     Const  MAKHOLD  As   String   =   " 22 "   ' 打洞命令|||消息格式:22+IP 
     Const  LOGINOK  As   String   =   " 23 "   ' 登陆成功 
     Const  SERVCLS  As   String   =   " 24 "   ' 服务器关闭 
     Const  MSGEND  As   String   =   " 25 "   ' 消息结束 
     Const  ONEOFF  As   String   =   " 26 "   ' 一个客户端下线(超时下线)
     Const  SEARCHCLIENT  As   String   =   " 27 "   ' 探测各个客户端是否存在

    
' 以下是客户端到客户端的消息开头 
     Const  HOLDOK  As   String   =   " 30 "   ' 打洞成功 
     Const  CHATMSG  As   String   =   " 31 "   ' 聊天消息 
     Const  CHTMSGEND  As   String   =   " 32 "   ' 聊天消息发送成功 
     Const  GIVEMEDATA  As   String   =   " 33 "   ' 添加数据订阅
     Const  NODATASEND  As   String   =   " 34 "   ' 取消数据订阅
     Const  GETDEVINFO  As   String   =   " 35 "   ' 获取工作站的基本信息

    
' 以下是工作站发送到客户端的命令:
     Const  RECDEVINFO  As   String   =   " 45 "   ' 工作站发送给服务器的设备配置信息
     Const  DATA  As   String   =   " 40 "         ' 表示发送的是数据信息,由工作站发送给客户端

    
' 以下是客户端的命名 
     Const  EXITPRO  As   String   =   " EXIT "   ' 退出命令 
     Const  SHOWULIST  As   String   =   " SHOWUSER "   ' 显示在线用户 
     Const  HELP  As   String   =   " HELP "   ' 显示帮助 
     Const  SEND  As   String   =   " SEND "   ' 发送消息 

    
' Const OldData As String = "40"

#End Region

#Region  "全局变量"

    
Delegate   Sub  myMethodDelegate( ByRef  myInData  As   Byte ())  ' 登陆时用的事件 
     Dim  msgSendEnd  As   Boolean   =   False   ' 消息是否发送成功,若发送成功,则会返回结束消息 
     Dim  ThListen  As   New  Thread( AddressOf  listen)  ' 监听的线程 
     Dim  ThSend  As  Thread  =   Nothing
    
Dim  ClientSocket  As   New  Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)  ' 客户端套节字的定义 
     Public  username  As   String   ' 当前用户名 
     Dim  ServerEP  As  IPEndPoint  ' 服务器的IPEP 
     Dim  holdBytes  As  [ Byte ]()  =  Encoding.Unicode.GetBytes(HOLDLINE  &  username)  ' 和服务器保持连接连接时用到的byte数组 
     Dim  getUrecCount  As   Integer
    
Dim  testHold  As   Boolean   =   False
    
Dim  testChat  As   Boolean   =   False
    
Private  receiveDone  As  ManualResetEvent  ' 在登陆时用来阻塞线程,等待收到数据 
     Private  sendDone  As  ManualResetEvent  ' 用来阴塞发送消息的线程.等待收到回送的确认消息  
     Private  holdDone  As  ManualResetEvent  ' 用来阻塞打洞时的线程 
     Private  chatDone  As  ManualResetEvent  ' 用来阻塞发送聊天消息时的线程 
     Public  Connected  As   Boolean   =   True     ' 用来表示是否和服务器连接成功
     Dim  timerDelegate  As   New  TimerCallback( AddressOf  holdonline)  ' 为保持在线状态弄得 
     Private  mytimer  As  Timer
    
Public  on_off  As   Boolean   =   False      ' 表示发送开关是否打开,有主任端连接即打开此开关,所有连接的主任端下线后即关闭
     Public  SendDataList  As  ArrayList
    
Const  movelenth  As   Integer   =   509   ' 最大为511,加上标志位为512,乘以2为传送的最大字节数:1024
     Private  sw  As  StreamWriter
    
Private  dealing  As   Boolean   =   False
    
Private  ReceiveDataList  As  DataQueue
    
' 此数为减去头一个标志位(表示此段是否结束:0表示未结束;1表示结束)剩余的字符长度
#End Region

#Region  "方法"

    
Public   Event  SendDDIinfo( ByVal  TgIP  As  IPEndPoint)
    
Public   Event  NetWorkError( ByVal  ErrStr  As   String )

    
' 主函数,程序入口,放到splash中运行: 
     Sub   New ()
        
Try
            
If  register.Reg.GetKey( " ServerIP " =   ""   Then
                ServerEP 
=   New  IPEndPoint(IPAddress.Parse( " 127.0.0.1 " ),  11000 )
            
Else
                ServerEP 
=   New  IPEndPoint(IPAddress.Parse(register.Reg.GetKey( " ServerIP " )),  11000 )   ' 正式版本专用,从注册表读取服务器地址
             End   If
            sw 
=   New  StreamWriter(Directory.GetCurrentDirectory  &   " \DataServer.log " True )
            
AddHandler  SendDDIinfo,  AddressOf  SendBasicInfo
            
' ********测试专用,测试版本不读注册表,本机就是服务器!********
             ' If getIdOfLocalhost() = "" Then
             '     '获取不到本机地址则退出
             '     RaiseEvent NetWorkError("找不到存在的连接")
             '     Exit Sub
             ' End If
             ' 假设本机只有一块网卡,邦定一个ip地址和端口(5555)
             ' 正式版从注册表中读取GUID作为名称:
             ' 模拟版本获取主机名为登录名称:
            username  =   " DataServer  "   &  Dns.GetHostName
            
Dim  LocalEP  As   New  IPEndPoint(IPAddress.Any,  5555 )
            ClientSocket.Bind(LocalEP)      
' 绑定本机端口
            ReceiveDataList  =   New  DataQueue
            
' 根据注册表中的ServerIp,向指定的服务器端口(11000)登录:
             Dim  i  As  Int16  =   1
            
While   Not  Login()
                
If  i  >   2   Then        ' 三次登录失败,则退出循环,直接帮定本机ip的5555端口。保证可以正常通讯
                     Me .Connected  =   False
                    
RaiseEvent  NetWorkError( " 登录失败! " )
                    
Exit   While
                
End   If
                i 
+=   1
            
End   While
            
' 登陆成功后.用一个timer,每隔50秒向服务器发送消息,保持在线状态跟在主机注册的端口 
            mytimer  =   New  Timer(timerDelegate,  Nothing 10000 50000 )
            ThListen.Start()
            SendDataList 
=   New  ArrayList
        
Catch  ex  As  Exception
            Debug.WriteLine(
" Client_New: "   &  Err.Description)
        
End   Try
    
End Sub

    
' 退出服务器的管理
     Public   Sub  ExitProcess()
        
Try   '
            sw.Close()
            sw 
=   Nothing
            exitApp()
            ClientSocket.Close()
            mytimer.Dispose()
            ThListen.Abort()
            Debug.WriteLine(
" 成功下线! " )
        
Catch  ex  As  Exception
            Debug.WriteLine(
" ExitProcess中报错: "   &  ex.Message)
        
End   Try
    
End Sub

    
' 一个工作站登陆到服务器
     Private   Function  Login()  As   Boolean
        
Try
            receiveDone 
=   New  ManualResetEvent( False )
            
Dim  userBytes  As  [ Byte ]()
            
Dim  userOK  As   Boolean   =   False
            userBytes 
=  Encoding.Unicode.GetBytes(LOGININ  &  username)
            
' 向服务器发送客户消息 
            ClientSocket.SendTo(userBytes, ServerEP)
            
Dim  data  As  [ Byte ]()  =   New   Byte ( 1024 ) {}
            
Dim  comStr  As   String   =  Encoding.Unicode.GetString(data,  0 4 )
            
' 异面的接收服务器回送的消息 
             Dim  DGrecv  As   New  myMethodDelegate( AddressOf  recvLogin)
            DGrecv.BeginInvoke(data, 
Nothing Nothing )
            
' 等待服务器回送消息的时长为10秒,否则为服务器超时 
            receiveDone.WaitOne( 500 True )
            
Dim  recvStr  As   String   =  Encoding.Unicode.GetString(data,  0 4 )
            
If  recvStr  =  comStr  Then
                Debug.WriteLine(
" 服务器超时.登陆失败!! " )
                
Return   False
            
End   If
            
If  Encoding.Unicode.GetString(data,  0 4 =  LOGINOK  Then
                Debug.WriteLine(
" 登陆成功!! " )
                
Return   True
            
Else
                Debug.WriteLine(
" 服务器未知错误,登陆失败!! " )
                
Return   False
            
End   If
        
Catch  ex  As  Exception
            Debug.WriteLine(
" Login: "   &  Err.Description)
        
End   Try
    
End Function

    
' 解除登陆函数中的线程阻止
     Sub  recvLogin( ByRef  inData  As   Byte ())

        ClientSocket.Receive(inData)
        receiveDone.Set()

    
End Sub

    
' 登出函数 
     Private   Sub  exitApp()
        
Try
            
Dim  loginOutStr  As   String   =  LOGINOUT  &  username
            
Dim  sendBytes  As  [ Byte ]()  =  Encoding.Unicode.GetBytes(loginOutStr)
            ClientSocket.SendTo(sendBytes, ServerEP)
        
Catch  ex  As  Exception
            Debug.WriteLine(
" 下线失败: "   &  Err.Description)
        
End   Try
    
End Sub

    
' 客户程序监听的函数 
     Sub  listen()
        
While   True
            
Try
                
Dim  recv  As   Integer   =   0   ' 收到的字节数 
                 Dim  datas  As  [ Byte ]()  =   New   Byte ( 1024 ) {}  ' 缓冲区大小 
                 Dim  sender  As   New  IPEndPoint(IPAddress.Any,  0 )
                
Dim  tempRemoteEP  As  EndPoint  =   CType (sender, EndPoint)
                recv 
=  ClientSocket.ReceiveFrom(datas, tempRemoteEP)       ' data存放接收到的数据,tempRemoteEP存放发送来的ip地址
                 Dim  tmpdata  As   New  DeclearData(datas, tempRemoteEP, recv)     ' 装进信息块中
                ReceiveDataList.AddItem(tmpdata)                             ' 将信息块装进本程序自己的缓冲区
                 If   Not  dealing  Then
                    
Dim  dealdatathread  As   New  Thread( AddressOf  DealData)
                    dealdatathread.Name 
=   " dealdata "
                    dealdatathread.Start()
                
End   If
            
Catch
                Debug.WriteLine(
" listen: "   &  Err.Description)
                WriteLog(
" listen: "   &  Err.Description)
            
End   Try
        
End   While
    
End Sub

    
' 处理不同机器发送过来的信息
     Private   Sub  DealData()
        
If   Not  dealing  Then
            dealing 
=   True
            
Dim  tmpmsg  As  DeclearData
            
While  ReceiveDataList.count  >   0
                
Try
                    tmpmsg 
=  ReceiveDataList.GetFirstItem
                    
Dim  msgHead  As   String   =  tmpmsg.datastr.Substring( 0 2 )
                    
' 可以侦听到的命令:
                    Debug.WriteLine( " 收到: "   &  tmpmsg.datastr)
                    
If  msgHead  <>   ""   Then
                        
Select   Case  msgHead
                            
Case  LOGININ
                                
' 如果有一个节点登陆:
                                 ' 暂时不做处理
                             Case  GIVEMEDATA          ' 添加一个接收数据的监视端
                                 If   Not  on_off  Then
                                    on_off 
=   True         ' 打开开关
                                     If  ThSend  Is   Nothing   Then     ' 如果此时发送数据的线程没有启动,则启动它
                                        ThSend  =   New  Thread( AddressOf  DataMove)
                                        ThSend.Start()
                                        Debug.WriteLine(
" 开始发送数据! " )
                                    
End   If
                                
End   If
                                AddRss(tmpmsg.datastr, tmpmsg.fromip)

                            
Case  NODATASEND          ' 取消一个接收数据的监视端
                                RemoveRss(tmpmsg.datastr, tmpmsg.fromip)

                            
Case  MSGEND              ' 控制数据发送成功返回标志
                                msgSendEnd  =   True
                                sendDone.Set()

                            
Case  HOLDOK              ' 保持在线信息返回
                                testHold  =   True
                                holdDone.Set()

                            
Case  CHTMSGEND           ' 发送聊天信息返回标志
                                testChat  =   True
                                chatDone.Set()

                            
Case  GETDEVINFO
                                
' 要求发送本工作站的基本信息:
                                SendBasicInfo(tmpmsg.fromip)

                            
Case  ONEOFF
                                
' 某个客户端超时下线:
                                 ' 检验此信息是否为服务器正确端口发送
                                 ' 检测该客户端是否正在接收我们的数据,如果是则终止
                             Case  SEARCHCLIENT
                                ReLogin(tmpmsg.fromip)
                            
Case   Else

                        
End   Select
                    
End   If
                
Catch  ex  As  Exception
                    Debug.WriteLine(
" 错误的数据: "   &  tmpmsg.datastr)
                    Debug.WriteLine(
" DealData: "   &  Err.Description)
                    WriteLog(
" 错误的数据: "   &  tmpmsg.datastr)
                    WriteLog(
" DealData: "   &  Err.Description)
                
Finally
                    ReceiveDataList.Remove()
                
End   Try
            
End   While
            dealing 
=   False
        
End   If
    
End Sub

    
' 一个客户端发送请求,要求本工作站向其发送数据,此请求只能由客户端发送
     ' 向设备实例的SendTO()数组添加该工作站的IP地址(本程序只向固定端口发送数据!)
     Private   Function  AddRss( ByVal  dt  As   String ByVal  ip  As  IPEndPoint)  As   Boolean
        
Dim  i, j  As   Integer
        
Dim  tmpsetup  As  ClassSetup
        
Dim  flag  As   Boolean   =   False
        
Dim  success  As   Boolean   =   False
        
Dim  findsetup  As   Boolean   =   False
        
Dim  id  As   String   =  dt.Substring( 2 , dt.Length  -   2 )
        
Try
            
For  i  =   0   To  DataSetUp.count  -   1
                tmpsetup 
=  DataSetUp.item(i)
                
If  id  =   ""   Then
                    flag 
=   False
                    
For  j  =   0   To  tmpsetup.SendTo.Length  -   1
                        
If  ( Not  tmpsetup.SendTo(j)  Is   Nothing AndAlso  tmpsetup.SendTo(j).Address.ToString  =  ip.Address.ToString  Then
                            
' 这个设备本来就向该客户端发送数据
                            flag  =   True
                            
Exit   For
                        
End   If
                    
Next
                    
If   Not  flag  Then
                        j 
=  tmpsetup.SendTo.Length
                        
ReDim   Preserve  tmpsetup.SendTo(j  +   1 )
                        tmpsetup.SendTo(j) 
=   New  IPEndPoint(ip.Address,  5556 )
                    
End   If
                    success 
=   True
                    findsetup 
=   True
                
ElseIf  tmpsetup.ID  =  id  Then            ' 正是要申请的设备,进行下一步判断:
                    findsetup  =   True      ' 找到了这个设备
                     If  tmpsetup.SendTo  Is   Nothing   Then
                        
ReDim   Preserve  tmpsetup.SendTo( 1 )
                        tmpsetup.SendTo(
0 =   New  IPEndPoint(ip.Address,  5556 )            ' 第一个申请的客户端
                        success  =   True
                        
Exit   For   ' i
                     Else
                        flag 
=   False
                        
For  j  =   0   To  tmpsetup.SendTo.Length  -   1
                            
If  ( Not  tmpsetup.SendTo(j)  Is   Nothing AndAlso  tmpsetup.SendTo(j).Address.ToString  =  ip.Address.ToString  Then     ' 重复申请
                                Debug.WriteLine( " 该客户端已经在接收数据了!这是违法操作! " )
                                flag 
=   True
                                
Exit   For      ' j
                             End   If
                        
Next  j
                        
If   Not  flag  Then          ' 正常的申请数据
                            flag  =   False          ' 检查前面是否有空的数组元素可用
                             For  j  =   0   To  tmpsetup.SendTo.Length  -   1
                                
If  tmpsetup.SendTo(j)  Is   Nothing   Then     ' 找到可用的
                                    tmpsetup.SendTo(j)  =   New  IPEndPoint(ip.Address,  5556 )
                                    success 
=   True
                                    flag 
=   True
                                    
Exit   For
                                
End   If
                            
Next  j
                            
If   Not  flag  Then      ' 没有找到可用的,重新扩展数组
                                j  =  tmpsetup.SendTo.Length
                                
ReDim   Preserve  tmpsetup.SendTo(j  +   1 )
                                tmpsetup.SendTo(j) 
=   New  IPEndPoint(ip.Address,  5556 )
                                success 
=   True
                            
End   If
                        
End   If
                        
Exit   For      ' i
                     End   If
                
End   If
            
Next  i
            
If   Not  findsetup  Then
                Debug.WriteLine(
" 没有找到该设备,ID信息错误! " )
            
End   If
            dt 
=   Nothing
            ip 
=   Nothing
            tmpsetup 
=   Nothing
            flag 
=   Nothing
            id 
=   Nothing
            
Return  success
        
Catch  ex  As  Exception
            Debug.WriteLine(
" AddRss: "   &  Err.Description)
        
End   Try
    
End Function

    
' 取消从本工作站获取数据
     ' 这个消息只由客户端发送
     Private   Function  RemoveRss( ByVal  dt  As   String ByVal  ip  As  IPEndPoint)  As   Boolean
        
Dim  i, j  As   Integer
        
Dim  tmpsetup  As  ClassSetup
        
Dim  flag  As   Boolean   =   False
        
Dim  findsetup  As   Boolean   =   False
        
Dim  id  As   String   =  dt.Substring( 2 , dt.Length  -   2 ' Encoding.Unicode.GetString(dt, 4, recv - 4)
         For  i  =   0   To  DataSetUp.count  -   1
            tmpsetup 
=  DataSetUp.item(i)
            
If  id  =   ""   Then
                
' 该客户端下线,取消所有向此客户端的发送:
                 If   Not  tmpsetup.SendTo  Is   Nothing   Then
                    
For  j  =   0   To  tmpsetup.SendTo.Length  -   1
                        
If  ( Not  tmpsetup.SendTo(j)  Is   Nothing AndAlso  tmpsetup.SendTo(j).Address.ToString  =  ip.Address.ToString  Then
                            
' Debug.WriteLine(tmpsetup.SendTo(j).ToString)
                            tmpsetup.SendTo(j)  =   Nothing
                            flag 
=   True
                            findsetup 
=   True
                            
' Exit For
                         End   If
                    
Next
                
End   If
            
ElseIf  tmpsetup.id  =  id  Then        ' 找到该设备
                findsetup  =   True
                flag 
=   False
                
For  j  =   0   To  tmpsetup.SendTo.Length  -   1
                    
If   Not  tmpsetup.SendTo(j)  Is   Nothing   Then
                        
' Debug.WriteLine(tmpsetup.SendTo(j).ToString & ip.ToString)
                         If  tmpsetup.SendTo(j).Address.ToString  =  ip.Address.ToString  Then         ' 找到了这个客户端地址
                            tmpsetup.SendTo(j)  =   Nothing
                            flag 
=   True
                            
' Exit For    'j
                         End   If
                    
End   If
                
Next
                
If   Not  flag  Then      ' 没有找到客户端地址
                    Debug.WriteLine( " 违法操作,该客户端没有申请过该工作站的数据! " )
                
End   If
                
Exit   For      ' i
             End   If
        
Next
        
If   Not  findsetup  Then
            Debug.WriteLine(
" 没有找到对应的设备!非法操作! " )
            
Return   False
        
End   If
        
If   Not  flag  Then       ' 没有找到客户端地址
            Debug.WriteLine( " 没有找到对应的客户端地址!非法操作! " )
            
Return   False
        
End   If
        
' 检查当前是否还有客户端在接收数据:
        flag  =   False
        
For  i  =   0   To  DataSetUp.count  -   1
            tmpsetup 
=  DataSetUp.item(i)
            
For  j  =   0   To  tmpsetup.SendTo.Length  -   1
                
If   Not  tmpsetup.SendTo(j)  Is   Nothing   Then
                    
' Debug.WriteLine("还有 " & tmpsetup.SendTo(j).ToString & " 在接收数据!")
                    flag  =   True           ' 找到一个!
                 End   If
            
Next
        
Next
        
' Debug.WriteLine("用户:" & ip.ToString & "需要取消接收数据")
         ' Debug.WriteLine(flag)
         If   Not  flag  Then
            
' 当前已经没有客户端需要本工作站发送数据了,关闭开关
            on_off  =   False          ' 关闭发送开关
            Debug.WriteLine( " 关闭发送开关! " )
            ThSend.Abort()
            ThSend 
=   Nothing
        
End   If
        dt 
=   Nothing
        
' recv = Nothing
        ip  =   Nothing
        i 
=   Nothing
        j 
=   Nothing
        tmpsetup 
=   Nothing
        flag 
=   Nothing
        findsetup 
=   Nothing
        id 
=   Nothing
    
End Function

    
' 用保持在线状态的函数 
     Private   Sub  holdonline( ByVal  state  As  [ Object ])
        
Try
            ClientSocket.SendTo(Encoding.Unicode.GetBytes(HOLDLINE 
&  username), ServerEP)
        
Catch  ex  As  Exception
            Debug.WriteLine(
" holdonline: "   &  ex.Message)
        
End   Try
    
End Sub

    
' 用于向各个客户端发送数据,此函数通过Send线程控制:
     ' 这个函数只用来发送数据信息,即以40开头的信息
     Public   Sub  DataMove()
        
Try
            
Dim  data  As   String
            
Dim  TempSend  As   String
            
Dim  TempDev  As  ClassSetup
            
Dim  i  As   Integer
            Debug.WriteLine(
" 启动发送器: " )
            
While  on_off
                Application.DoEvents()
                
If  SendDataList.Count  >   0   Then        ' 如果发送的链表中有数据,则按照顺序发送:
                    TempDev  =   CType (SendDataList.Item( 0 ), ClassData).myDevice        ' 获取是哪个设备要求发送的,空代表是本系统要求发送的,而不是某个设备的数据信息
                    data  =   CType (SendDataList.Item( 0 ), ClassData).mydata             ' 获取数据
                     ' 发送本数据:
                     For  i  =   0   To  TempDev.SendTo.Length  -   1
                        
If   Not  TempDev.SendTo(i)  Is   Nothing   Then                      ' 向所有需要接收本设备的客户端发送
                            SendLongData(data, TempDev.SendTo(i))
                        
End   If
                    
Next
                    
CType (SendDataList.Item( 0 ), ClassData).dispose()                 ' 将信息块释放掉
                    SendDataList.RemoveAt( 0 )                                         ' 删除此信息块
                 End   If
                Thread.Sleep(
100 )
            
End   While
            data 
=   Nothing
            TempSend 
=   Nothing
            Debug.WriteLine(
" 发送器结束 " )
        
Catch  ex  As  Exception
            Debug.WriteLine(
" DataMove: "   &  Err.Description)
        
End   Try
    
End Sub

    
' 将一整串长数据发送到指定的ip地址:
     ' 格式:40+标志量+数据
     Private   Function  SendLongData( ByVal  thedata  As   String ByVal  ip  As  IPEndPoint)  As   Boolean
        
Try
            
Dim  i  As   Integer
            
Dim  head  As   String   =  thedata.Substring( 0 2 )
            
Dim  TempSend  As   String
            
Dim  sendbytes()  As   Byte
            thedata 
=  thedata.Substring( 2 , thedata.Length  -   2 )                           ' 获取除了数据头之外的所有数据
             If  thedata.Length  >  movelenth  Then                                            ' 第一次数据!
                TempSend  =  head  &   " 0 "   &  thedata.Substring( 0 , movelenth)                  ' 添加0,表示数据的开始
                thedata  =  thedata.Substring(movelenth, thedata.Length  -  movelenth)       ' 将发送出去的那些字符除掉
                sendbytes  =  Encoding.Unicode.GetBytes(TempSend)
                ClientSocket.SendTo(sendbytes, ip)                                      
' 发送本段信息
                Thread.Sleep( 100 )
                
While  thedata.Length  >  movelenth                                         ' 如果剩下的数据大小大于可以发送的字节数,则拆分
                     ' 发送:
                    TempSend  =  head  &   " 2 "   &  thedata.Substring( 0 , movelenth)              ' 添加2,表示数据的中间部分
                    thedata  =  thedata.Substring(movelenth, thedata.Length  -  movelenth)   ' 将发送出去的那些字符除掉
                    sendbytes  =  Encoding.Unicode.GetBytes(TempSend)
                    ClientSocket.SendTo(sendbytes, ip)                                  
' 发送本段信息
                    Thread.Sleep( 100 )
                
End   While
                
If  thedata.Length  >   0   Then                                                ' 发送最后一段信息
                    TempSend  =  head  &   " 1 "   &  thedata                                      ' 添加1,表示是数据的结束
                    sendbytes  =  Encoding.Unicode.GetBytes(TempSend)
                    ClientSocket.SendTo(sendbytes, ip)
                    Thread.Sleep(
100 )
                
End   If
            
Else
                TempSend 
=  head  &   " 3 "   &  thedata                                          ' 添加3,表示这里是全部数据一次性传送完毕
                sendbytes  =  Encoding.Unicode.GetBytes(TempSend)
                ClientSocket.SendTo(sendbytes, ip)                                      
' 发送本段信息
             End   If
            i 
=   Nothing
            head 
=   Nothing
            thedata 
=   Nothing
            ip 
=   Nothing
            TempSend 
=   Nothing
            sendbytes 
=   Nothing
            
Return   True
        
Catch  ex  As  Exception
            Debug.WriteLine(
" SendLongData:  "   &  Err.Description)
            
Return   False
        
End   Try
    
End Function

    
' 获取本地地址:
     Private   Function  getIdOfLocalhost()  As   String
        
Try
            
Dim  addressList  As  System.Net.IPAddress()  =  Dns.GetHostByName(Dns.GetHostName()).AddressList
            
Dim  j  As   Integer             ' 定义的循环变量j,得到本地机的ip
             For  j  =   0   To  addressList.Length  -   1
                
If  ServerEP.Address.GetAddressBytes( 0 =  addressList(j).GetAddressBytes( 0 And  ServerEP.Address.GetAddressBytes( 1 =  addressList(j).GetAddressBytes( 1 And  ServerEP.Address.GetAddressBytes( 2 =  addressList(j).GetAddressBytes( 2 Then
                    
Return  addressList(j).ToString()
                
End   If
            
Next  j
            
Return   ""
        
Catch  ex  As  Exception
            Debug.WriteLine(
" getIdOfLocalhost: "   &  Err.Description)
        
End   Try
    
End Function

    
' 发送本工作站的基本信息:(本函数执行的时机由接口控制,一旦出现新的设备或配置完成即执行一次)
     ' 如果需要发送的目标为空,则说明是发送给服务器的
     ' 不为空,则是发送给某个客户端的
     Public   Sub  SendBasicInfo( Optional   ByVal  sendtoEP  As  IPEndPoint  =   Nothing )
        
Try
            
Dim  tmpstr  As   String   =  frmShowArguments.SaveConfig( True )
            
Dim  head  As   String   =  RECDEVINFO
            
Dim  TempSend  As   String
            
Dim  sendBytes()  As   Byte
            
Dim  movelenth  As   Integer   =   509   ' 最大为511,加上标志位为512,乘以2为传送的最大字节数:1024
             ' 重新组合配置文件:
             If  sendtoEP  Is   Nothing   Then  sendtoEP  =  ServerEP
            
While  tmpstr.Length  >  movelenth                                    ' 如果数据大小大于可以发送的字节数,则拆分
                 ' 发送:
                TempSend  =  head  &   " 0 "   &  tmpstr.Substring( 0 , movelenth)         ' 添加0,表示数据未结束
                tmpstr  =  tmpstr.Substring(movelenth, tmpstr.Length  -  movelenth)
                sendBytes 
=  Encoding.Unicode.GetBytes(TempSend)
                ClientSocket.SendTo(sendBytes, sendtoEP)
                Thread.Sleep(
100 )
            
End   While
            
If  tmpstr.Length  >   0   Then                                           ' 发送最后一段信息
                TempSend  =  head  &   " 1 "   &  tmpstr
                sendBytes 
=  Encoding.Unicode.GetBytes(TempSend)
                ClientSocket.SendTo(sendBytes, sendtoEP)
                Thread.Sleep(
100 )
            
End   If
            Debug.WriteLine(
" "   &  sendtoEP.ToString  &   " 发送配置信息 " )
            tmpstr 
=   Nothing
            head 
=   Nothing
            TempSend 
=   Nothing
            sendBytes 
=   Nothing
            sendtoEP 
=   Nothing
            movelenth 
=   Nothing
        
Catch  ex  As  Exception
            Debug.WriteLine(
" SendBasicInfo: "   &  Err.Description)
        
End   Try
    
End Sub

    
' 用于回应服务器服务程序发送的探测信息
     ' 只是一个回应,不对服务器发回的确认成功信息做任何处理
     Private   Sub  ReLogin( ByVal  TheServerEP  As  IPEndPoint)
        
Try
            
Dim  userBytes  As  [ Byte ]()
            userBytes 
=  Encoding.Unicode.GetBytes(LOGININ  &  username)
            
' 向服务器发送客户消息 
            ClientSocket.SendTo(userBytes, TheServerEP)
        
Catch  ex  As  Exception
            Debug.WriteLine(
" ReLogin: "   &  Err.Description)
        
End   Try
    
End Sub

    
Sub  WriteLog( ByVal  msg  As   String )
        Debug.WriteLine(msg)
        sw.WriteLine(msg)
        sw.Flush()
    
End Sub

#End Region

End Class


注:DeclearData和DataQueue两个类参见上一篇文章: .net中的socket异步通信实现--服务器端代码

转载于:https://www.cnblogs.com/yyshenren/archive/2008/07/10/1240154.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值