首页 > 开发 > 综合 > 正文

一个SDK里做聊天室的例子(2)

2024-07-21 02:21:59
字体:
来源:转载
供稿:网友


    
    
    ' nested enum for supported states
    public enum status
        listening
        connected
    end enum 'status
    
    
    ' start up the talker's functionality
    public sub start()
        threadpool.queueuserworkitem(new system.threading.waitcallback(addressof establishsocket))
    end sub 'start
    
    
    ' establish a socket connection and start receiving
    private sub establishsocket(byval state as object)
        try
            ' if not client, setup listner
            if not client then
                dim listener as socket

                try
                    listener = new socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp)
                    listener.blocking = true
                    listener.bind(endpoint)
                    setstatus(status.listening)
                    listener.listen(0)
                    socket = listener.accept()
                    listener.close()
                catch e as socketexception
                    ' if there is already a listener on this port try client
                    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, "error initializing socket:" & controlchars.crlf & e.tostring())
                    end if
                end try
            end if

            ' try a client connection
            if client then
                dim temp as new socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp)
                temp.blocking = true
                temp.connect(endpoint)
                socket = temp
            end if

            ' if it all worked out, create stream objects
            if not (socket is nothing) then
                setstatus(status.connected)
                dim stream as new networkstream(socket)
                reader = new streamreader(stream)
                writer = new streamwriter(stream)
                raiseevent notifications(notification.initialized, me)
            else
                raiseevent notifications(notification.errornotify, "failed to establish socket")
            end if

            ' start receiving talk
            ' note: on w2k and later platforms, the networkstream.read()
            ' method called in receivetalke will generate an exception when
            ' the remote connection closes. we handle this case in our
            ' catch block below.
            receivetalk()

            ' on win9x platforms, networkstream.read() returns 0 when
            ' the remote connection closes, prompting a graceful return
            ' from receivetalk() above. we will generate a notification.end
            ' message here to handle the case and shut down the remaining
            ' wintalk instance.
            raiseevent notifications(notification.endnotify, "remote connection has closed.")
            
        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, "remote connection has closed.")
            else
                raiseevent notifications(notification.errornotify, "socket error:" & controlchars.crlf & e.message)
            end if
        catch e as exception
            raiseevent notifications(notification.errornotify, "socket error:" & controlchars.crlf & e.message)
        end try
    end sub 'establishsocket


    ' send text to remote connection
    public sub sendtalk(byval newtext as string)
        dim send as string
        ' is this an append
        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)
            ' or a complete replacement
        else
            send = string.format("r{0}:{1}", newtext.length, newtext)
        end if
        ' send the data and flush it out
        writer.write(send)
        writer.flush()
        ' save the text for future comparison
        prevsendtext = newtext
    end sub 'sendtalk


    ' send a status notification
    private sub setstatus(byval statusobj as status)
        me.statusobj = statusobj
        raiseevent notifications(notification.statuschange, statusobj)
    end sub 'setstatus


    ' receive chat from remote client
    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
                goto continuewhile1
            end if

            select case readmode
                case 1
                    if counter = commandbuffer.length then
                        readmode = 0
                        goto continuewhile1
                    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.received, 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()
                            case else
                                prevreceivetext += textobj.tostring()
                        end select
                        readmode = 1

                        raiseevent notifications(notification.received, prevreceivetext)
                    end if
                case else
                    readmode = 0
                    goto continuewhile1
            end select
continuewhile1:
        end while
    end sub 'receivetalk

    private socket as socket

    private reader as textreader
    private writer as textwriter

    private client as boolean
    private endpoint as ipendpoint

    private prevsendtext as string
    private prevreceivetext as string
    private statustext as string

    private statusobj as status
end class 'talker
 
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表