Windows socket server and client example(TCP/IP)

Share your advanced PureBasic knowledge/code with the community.
BalrogSoft
Enthusiast
Enthusiast
Posts: 203
Joined: Sat Apr 26, 2003 6:33 pm
Location: Spain
Contact:

Windows socket server and client example(TCP/IP)

Post by BalrogSoft »

Code updated For 5.20+

Hi, i was playing with windows sockets through win32 api, i made a server and client with TCP/IP protocol, i hope that it can help to someone.

Server code:

Code: Select all

; TCP/IP Server using sockets of Win32 API by Balrog software
; To create a server the main steps are this:
; - Initialise Winsock with WSAStartup_()
; - Create the socket with socket_()
; - Bind the socket with bind_(), to associate a local address with the socket.
; - Listen to a client connexion with listen_().
; - And the server is ready to transfer data between client and server.

OpenConsole()

  ; Initialize Winsock.
  wsaData.WSADATA
  iResult = WSAStartup_($101, @wsaData)

  If iResult <> #NO_ERROR
    PrintN("Error at WSAStartup()")
  EndIf

  ; Create a socket.
  serversocket = socket_(#AF_INET, #SOCK_STREAM, #IPPROTO_TCP)
  If serversocket = #INVALID_SOCKET
    PrintN("Error at socket(): " + Str(WSAGetLastError_()))
    WSACleanup_()
    End
  EndIf

  ; Bind the socket to associate a local address to the socket.
  *ptr = service.sockaddr_in
  
  service\sin_family = #AF_INET
  service\sin_addr = inet_addr_("127.0.0.1")
  service\sin_port = htons_(6667)
 
  If bind_(serversocket, *ptr, SizeOf(sockaddr_in)) = #SOCKET_ERROR
    PrintN("bind() failed.")
    closesocket_(serversocket)
    End
  EndIf
    
  ; Listen for incomming connection ,with 255 as maximum length to which the queue 
  ; of pending connections may grow.
  If listen_(serversocket, 255) = #SOCKET_ERROR
    CloseSocket_(clientsocket)
    WSACleanup_()
    PrintN("Error listening on socket.")
    End
  EndIf

  PrintN("Waiting for a client to connect...")
  
  ; Wait to a new client, you can use accept_() to check for new client connected
  AcceptSocket = #SOCKET_ERROR
  While AcceptSocket = #SOCKET_ERROR
    AcceptSocket = accept_(serversocket, #NULL, #NULL)
    If acceptsocket > 0
      clientsocket = acceptsocket 
    EndIf
  Wend
   
  ; Send and receive Data.
  sendbuf.s = "Server: Send data."
  bytesSent = send_(clientsocket, @sendbuf, Len(sendbuf), 0)
  
  PrintN("Bytes Sent: "+ Str(bytesSent))

  recvbuf.s = Space(32)
  
  Repeat
    bytesRecv = recv_( clientsocket, @recvbuf, 32, 0)
  Until bytesRecv > 0
  
  PrintN("Bytes Received: " + Str(bytesRecv))
  PrintN(recvbuf)
  
  Input()
  
  closesocket_(serversocket)
  WSACleanUp_()
CloseConsole()
Client code:

Code: Select all

; TCP/IP Client using sockets of Win32 API by Balrog software
; To create a client the main steps are this:
; - Initialise Winsock with WSAStartup_()
; - Create the socket with socket_()
; - Connect to the server with connect_()
; - And the server is ready to transfer data between client and server.

OpenConsole() 

  ; Initialise Winsock. 
  wsaData.WSADATA
  iResult = WSAStartup_($101, @wsaData)
  If iResult <> #NO_ERROR
    PrintN("Error at WSAStartup()")
  EndIf
  
  ; Create a socket for client
  clientsocket = socket_(#AF_INET, #SOCK_STREAM, #IPPROTO_TCP)

  If clientsocket = #INVALID_SOCKET
    PrintN( "Error at socket(): " + Str(WSAGetLastError_()))
    WSACleanup_()
    End
  EndIf

  ; Connect to a server.
  *ptr = clientService.sockaddr_in

  clientService\sin_family = #AF_INET
  clientService\sin_addr = inet_addr_("127.0.0.1")
  clientService\sin_port = htons_(6667)

  If connect_(clientsocket, *Ptr, SizeOf(sockaddr_in)) = #SOCKET_ERROR
    PrintN("Failed to connect")
    CloseSocket_(clientsocket)
    WSACleanup_()
    End
  EndIf

  ; Send and receive data.

  recvbuf.s = Space(32)
  Repeat
    bytesRecv = recv_( clientsocket, @recvbuf, 32, 0)
  Until bytesRecv > 0
  PrintN("Bytes received: " + Str(bytesRecv))
  PrintN(recvbuf)
  
  sendbuf.s = "Client: Send data."
  bytesSent = send_( clientsocket, @sendbuf, Len(sendbuf), 0 )
  PrintN( "Bytes Sent: " + Str(bytesSent))

  CloseSocket_(clientsocket)
  WSACleanUp_()
   
  Input()
CloseConsole()
Bye!!!
Shannara
Addict
Addict
Posts: 1808
Joined: Thu Oct 30, 2003 11:19 pm
Location: Emerald Cove, Unformed

Post by Shannara »

One of the advantages I can see that this has over the PB network library, is that you can actually bind to an IP (which is a must in a server environment), but I have two questions...

1. Are you planning on adding IOCP support?
2. How in the world do you send and recieve strings??
BalrogSoft
Enthusiast
Enthusiast
Posts: 203
Joined: Sat Apr 26, 2003 6:33 pm
Location: Spain
Contact:

Post by BalrogSoft »

Hi Shannara, for your first question i don't have an answer, because i don't know what is IOCP, for your second question, i don't understand very well when you say "world", do you refer about send data through internet? i made the example to use the local ip address 127.0.0.1, but you can use your real ip address to create a server that will work on internet. You can get your host name with gethostname_() and convert to a ip address, put this code after initialise winsock (i got this code on winsock_lib available on purearea code archive):

Code: Select all

  name.s=Space(64)
  gethostname_(@name,64)
  PrintN(name)
  *retval = gethostbyname_(@name)
  If *retval <> 0
  iplong=PeekL(PeekL(PeekL(*retval+12)))
  EndIf
  ipaddress.s=(StrU(PeekB(@iplong),#Byte)+"."+StrU(PeekB(@iplong+1),#Byte)+"."+StrU(PeekB(@iplong+2),#Byte)+"."+StrU(PeekB(@iplong+3),#Byte))
  PrintN(ipaddress)
User avatar
NoahPhense
Addict
Addict
Posts: 1999
Joined: Thu Oct 16, 2003 8:30 pm
Location: North Florida

Re: Windows socket server and client example(TCP/IP)

Post by NoahPhense »

Veru nice.. good to see ppl moving forward with PB networking.. maybe
this helps.. for diagnostics and building..

http://www.pyxia.com/community/viewtopic.php?t=8111

- np
Tranquil
Addict
Addict
Posts: 952
Joined: Mon Apr 28, 2003 2:22 pm
Location: Europe

Post by Tranquil »

Nice to see a complete API network code. But I just want to add that there is no error handling in this code for sending and receiving datas. For use internet this is highly recomanded.

Example:

bytesSent = send_(clientsocket, @sendbuf, Len(sendbuf), 0

You check for BytesSent but never compare this with len(sendbuf) in your code. Why? It could be possible that you need to call send_ again and again to send your string completely. Anyway, a socket_error could be returned by send_() and you have to use lasterror() to check for it.

For sending strings I use an own code where I added a header to the datapacket with the length of the string.

Here is an example for networking ive done with PB one year ago. It should work in 3.91 too.
This is the correct way of sending and receiving datas.

Server:

Code: Select all

; Chat Server X-Ample by Mike Delling
;
; With complete documentation for correctly networking in PB. :o)

If InitNetwork()=0
  MessageRequester("","Could not initialize WSA.",0)
  End
EndIf

hServer=CreateNetworkServer(6000)

If hServer=0
  MessageRequester("","Could not open server.",0)
EndIf


hWin=OpenWindow(0,0,0,0,0,#PB_Window_Invisible,"")

If hWin=0
  MessageRequester("","Could not open window.",0)
  End
EndIf

; -----------------------------------------
: Dimenstions & Structures & Constants
; -----------------------------------------

   Structure slot
      socket.l                                            ; Socket Number of User
      nickname.s                                          ; Prior and Alternative Nickname of User
      *receivebuffer.l                                           ; Pointer to Receivebuffer
      totalreceived.l                                     ; Read-Buffer Position
      receiveexpected.l                                   ; Wait for this size!
    EndStructure

#NetworkEvent   = #WM_User +1       ; For incomeing events from server

#MaxCommands    = 10
#MaxUser        = 100
#BufferSize     = 12000

Dim commands$(#MaxCommands)
Dim slot.slot(#MaxUser)


; -----------------------------------------
; Some Procedures
; -----------------------------------------


   Procedure.w MyGetCommand(a$) 
        For a = 0 To #MaxCommands : commands$(a) = "" : Next
        len = Len(a$) : ak = 1
        ;
        Repeat
          letter$ = Mid(a$,ak,2)
          If letter$ <> "@!"
            letter$ = Mid(a$,ak,1)
            commands$(akcommand)+letter$ : ak + 1
          EndIf
          ;
          If letter$ = "@!"
            akcommand + 1 : ak + 2
          EndIf
        Until ak >= len
        ;
        ProcedureReturn akcommand
    EndProcedure

;-----------------------------------
; PROC - Send Datas through network
;-----------------------------------
    
    Procedure MySend(id,txt$)
    
    ; calculate bufferlength
    
    length.l=Len(txt$)+1        ; String + EOL
    length.l+4                  ; Packet length at beginning
    length.l+4                  ; CRC32

    *mem.l=GlobalAlloc_(#GMEM_FIXED | #GMEM_ZEROINIT, length.l)
    
    PokeL(*mem.l,length.l)      ; Store the Header (Size of Packet)
    PokeS(*mem.l+4,txt$)        ; Store String (Datas)

    crc.l=CRC32Fingerprint(*mem.l+4,length.l-8)   ; Create CRC32 Checksum
    PokeL(*mem.l+length.l-4,crc.l)                ; Store it at the end of the packet
    
    Repeat                                       ; Loop for Datasend
      send=send_(id,*mem.l,length,0)              ; Send our Datas
      sended+send                                 ; Count our sended Bytes
      If send=#SOCKET_ERROR
          wsaerror=wsagetlasterror_()
          If wsaerror=#WSANOTINITIALISED:err$="Wsa not initialized":EndIf
          If wsaerror=#WSAENETDOWN :err$="The Windows Sockets implementation has detected that the network subsystem has failed.":EndIf
          If wsaerror=#WSAENOTCONN :err$="Socket not connected.":EndIf
          If wsaerror=#WSAEINTR :err$="The (blocking) call was canceled using WSACancelBlocking":EndIf
          If wsaerror=#WSAEINPROGRESS :err$="A blocking Windows Sockets operation is in progress.":EndIf
          If wsaerror=#WSAENOTSOCK :err$="The descriptor is not a socket.":EndIf
          If wsaerror=#WSAEOPNOTSUPP :err$="MSG_OOB was specified, but the socket is not of type SOCK_STREAM.":EndIf
          If wsaerror=#WSAESHUTDOWN :err$="The socket has been shut down; it is not possible to recv on a socket after shutdown has been invoked with how set to 0 or 2.":EndIf
          If wsaerror=#WSAEMSGSIZE :err$="The datagram was too large to fit into the specified buffer and was truncated.":EndIf
          If wsaerror=#WSAEINVAL :err$="The socket has not been bound with bind.":EndIf
          If wsaerror=#WSAECONNABORTED :err$="The virtual circuit was aborted due to timeout or other failure.":EndIf
          If wsaerror=#WSAECONNRESET :err$="The virtual circuit was reset by the remote side.":EndIf
          If wsaerror=#WSAEWOULDBLOCK :err$="The socket is marked as nonblocking":EndIf        
          If wsaerror=#WSAEWOULDBLOCK:send=0:sended=0:Delay(250):EndIf 
      EndIf ; Errorcheck

    Until sended>=length Or send=#SOCKET_ERROR   ; Loop as long as all Datas has been send
    GlobalFree_(*mem)                                 ; Free our Memory again
    ProcedureReturn send
    EndProcedure


If WSAAsyncSelect_(hServer,hWin,#NetworkEvent,#FD_ACCEPT|#FD_READ|#FD_CLOSE)<>0
  MessageRequester("","Could not catch events!",0)
EndIf


Procedure findfreeslot()
  result=-1
  Repeat
    If slot(ak)\socket=0    ; no Socket here, so the slot is free
      result=ak
    Else
      ak+1
    EndIf
  Until ak=#MaxUser Or result>=0
ProcedureReturn result
EndProcedure

Procedure finduser(id)
  result=-1
  Repeat
    If slot(ak)\socket=id
      result=ak
    Else
      ak+1
    EndIf
  Until ak=#MaxUSer Or result=>0
ProcedureReturn result
EndProcedure


OpenConsole()
PrintN("Server running...")
Repeat

    winevent=WaitWindowEvent()

    If winevent=#NetworkEvent           ; Incoming connection/ Datas
        netevent=NetworkServerEvent()    ; This command updates the NetworkClientID() Command
        id=NetworkClientID()
        
        If netevent=1
          slot=findfreeslot()
          slot(slot)\socket=id          ; We assign the user to show that this socket is in use
          slot(slot)\receivebuffer=GlobalAlloc_(#GMEM_FIXED | #GMEM_ZEROINIT, #Buffersize)             ; We are in need of some memory for our user       
          PrintN("Incoming connection on socket "+Str(id)+" on slot "+Str(slot))
        EndIf
        
        If netevent=4                   ; User disconnect, free mem and slot
          slot=finduser(id)
          PrintN("Slot "+Str(slot)+" free again.Socket "+Str(slot(slot)\socket)+" closed.")
          slot(slot)\socket=0
          globalfree_(slot(slot)\receivebuffer)
        EndIf
        
        If netevent=2 ; Datas received
          ; We have to find out the slot for the user who send us the datas
          slot=finduser(id)
          
         If slot(slot)\receiveexpected>0
           *receivebuffer=slot(slot)\receivebuffer
           received=recv_(id,*receivebuffer+slot(slot)\totalreceived,slot(slot)\receiveexpected-slot(slot)\totalreceived,0)
       
           If received<>#SOCKET_ERROR 
             slot(slot)\totalreceived+received
             If slot(slot)\totalreceived=slot(slot)\receiveexpected
                command$=PeekS(*receivebuffer+4)                  ; Get our Command-String from Memorybuffer
                anz=MyGetCommand(command$)                        ; Tokanize our Command-String
                slot(slot)\totalreceived=0                        ; Datapacket complete, reset value and wait for new one
                slot(slot)\receiveexpected=-1                     ; Wait for new packetheader but do not execute the next part!
                
                
                ; Commandprozessing follows here:
                
                If commands$(0)="STRG"            ; User sends a Chatstring, send it to all other clients
                  For ak=0 To #MaxUser
                    If slot(ak)\socket<>0 And slot(ak)\socket<>id
                      res=mysend(slot(ak)\socket,"STRG@!"+commands$(1)+"@!"+commands$(2)+"@!")
                      PrintN("Send message to socket:"+Str(slot(ak)\socket))
                    EndIf
                  Next ak
                EndIf
                
                If commands$(0)="ENTR"
                  slot=finduser(id)
                  slot(slot)\nickname = commands$(1)
                  For ak=0 To #MaxUser
                    If slot(ak)\socket<>0 And slot(ak)\socket<>id
                      res=mysend(slot(ak)\socket,"ENTR@!"+commands$(1)+"@!")
                      PrintN("Send ENTR message to socket:"+Str(slot(ak)\socket))
                    EndIf 
                  Next ak
                EndIf
                
                ; End Command STRG
                
             EndIf
           EndIf
      
         EndIf ; End Receive Datas
     
      If slot(slot)\totalreceived<3 And slot(slot)\receiveexpected=0     ; Unknown headersize, get header first
        *receivebuffer=slot(slot)\receivebuffer
        received=recv_(id,*receivebuffer+slot(slot)\totalreceived,4-slot(slot)\totalreceived,0)
        If received<>#SOCKET_ERROR
          If received=4:slot(slot)\receiveexpected=PeekL(*receivebuffer):EndIf    ; Grad HeaderSize
          slot(slot)\totalreceived+received
        EndIf
      EndIf
      
      If slot(slot)\receiveexpected=-1:slot(slot)\receiveexpected=0:EndIf
        
        EndIf                     ; Datas received        
    EndIf                         ; End Networkevent 


Until esc=1
; ExecutableFormat=Windows
; CursorPosition=28
; FirstLine=1
; Executable=D:\server.exe
; DisableDebugger
; EOF

Client:

Code: Select all

; Chat Server X-Ample by Mike Delling
;
; With complete documentation for correctly networking in PB. :o)

If InitNetwork()=0
  MessageRequester("","Could not initialize WSA.",0)
  End
EndIf



hWin=OpenWindow(0,0,0,600,200,#PB_Window_ScreenCentered|#PB_Window_SystemMenu,"PB Chat Client")

If hWin=0
  MessageRequester("","Could not open window.",0)
  End
EndIf

If CreateGadgetList(hWin)=0
  MessageRequester("","Could not Create Gadgetlist.",0)
EndIf

; -----------------------------------------
: Dimenstions & Structures & Constants
; -----------------------------------------

#NetworkEvent   = #WM_User +1       ; For incomeing events from server

#MaxCommands    = 10
#Maxlines       = 1024


Dim commands$(#MaxCommands)

*receivebuffer=GlobalAlloc_(#GMEM_FIXED | #GMEM_ZEROINIT, 12000)
; -----------------------------------------
; Some Procedures
; -----------------------------------------


   Procedure.w MyGetCommand(a$) 
        For a = 0 To #MaxCommands : commands$(a) = "" : Next
        len = Len(a$) : ak = 1
        ;
        Repeat
          letter$ = Mid(a$,ak,2)
          If letter$ <> "@!"
            letter$ = Mid(a$,ak,1)
            commands$(akcommand)+letter$ : ak + 1
          EndIf
          ;
          If letter$ = "@!"
            akcommand + 1 : ak + 2
          EndIf
        Until ak >= len
        ;
        ProcedureReturn akcommand
    EndProcedure

;-----------------------------------
; PROC - Send Datas through network
;-----------------------------------
    
    Procedure MySend(id,txt$)
    
    ; calculate bufferlength
    
    length.l=Len(txt$)+1        ; String + EOL
    length.l+4                  ; Packet length at beginning
    length.l+4                  ; CRC32

    *mem.l=GlobalAlloc_(#GMEM_FIXED | #GMEM_ZEROINIT, length.l)
    
    PokeL(*mem.l,length.l)      ; Store the Header (Size of Packet)
    PokeS(*mem.l+4,txt$)        ; Store String (Datas)

    crc.l=CRC32Fingerprint(*mem.l+4,length.l-8)   ; Create CRC32 Checksum
    PokeL(*mem.l+length.l-4,crc.l)                ; Store it at the end of the packet
    
    Repeat                                       ; Loop for Datasend
      send=send_(id,*mem.l,length,0)              ; Send our Datas
      sended+send                                 ; Count our sended Bytes
      If send=#SOCKET_ERROR
          wsaerror=wsagetlasterror_()
          If wsaerror=#WSANOTINITIALISED:err$="Wsa not initialized":EndIf
          If wsaerror=#WSAENETDOWN :err$="The Windows Sockets implementation has detected that the network subsystem has failed.":EndIf
          If wsaerror=#WSAENOTCONN :err$="Socket not connected.":EndIf
          If wsaerror=#WSAEINTR :err$="The (blocking) call was canceled using WSACancelBlocking":EndIf
          If wsaerror=#WSAEINPROGRESS :err$="A blocking Windows Sockets operation is in progress.":EndIf
          If wsaerror=#WSAENOTSOCK :err$="The descriptor is not a socket.":EndIf
          If wsaerror=#WSAEOPNOTSUPP :err$="MSG_OOB was specified, but the socket is not of type SOCK_STREAM.":EndIf
          If wsaerror=#WSAESHUTDOWN :err$="The socket has been shut down; it is not possible to recv on a socket after shutdown has been invoked with how set to 0 or 2.":EndIf
          If wsaerror=#WSAEMSGSIZE :err$="The datagram was too large to fit into the specified buffer and was truncated.":EndIf
          If wsaerror=#WSAEINVAL :err$="The socket has not been bound with bind.":EndIf
          If wsaerror=#WSAECONNABORTED :err$="The virtual circuit was aborted due to timeout or other failure.":EndIf
          If wsaerror=#WSAECONNRESET :err$="The virtual circuit was reset by the remote side.":EndIf
          If wsaerror=#WSAEWOULDBLOCK :err$="The socket is marked as nonblocking":EndIf        
          If wsaerror=#WSAEWOULDBLOCK:send=0:sended=0:Delay(250):EndIf 
      EndIf ; Errorcheck

    Until sended>=length Or send=#SOCKET_ERROR   ; Loop as long as all Datas has been send
    GlobalFree_(*mem)                                 ; Free our Memory again
    ProcedureReturn send
    EndProcedure


#HostIPText     = 1
#HostString     = 2

#NickText       = 3
#NickString     = 4

#Connect        = 5
#ChatWindow     = 6
#ChatText       = 7

#Send           = 8


#ReturnKey      = 1

TextGadget    (#HostIPText,10,13,50,20,"Host/IP:")
StringGadget  (#HostString,70,10,150,20,"127.0.0.1")

TextGadget    (#NickText,230,13,50,20,"Nickname:")
StringGadget  (#NickString,290,10,150,20,"Eliot")

ButtonGadget  (#Connect,450,10,100,20,"Connect")

ListIconGadget(#ChatWindow,10,40,580,120,"",500)
StringGadget  (#ChatText,10,170,500,20,"")
ButtonGadget  (#Send,520,170,70,20,"Send"):AddKeyboardShortcut(0,#PB_Shortcut_Return,#ReturnKey)


Procedure showmsg(msg$)
Shared lines,maxlines
AddGadgetItem(#ChatWindow,lines,msg$)
SendMessage_(GadgetID(#ChatWindow),#LVM_ENSUREVISIBLE,lines,1)
lines+1
EndProcedure


Procedure window(WindowID, Message, wParam, lParam) 
    Shared hSocket,*receivebuffer.l,totalreceived.l,receiveexpected.l,received
    Result = #PB_ProcessPureBasicEvents 
 ; Handle Networkevents here
      
      If Message=#NetworkEvent
 
      serverevent=NetworkClientEvent(hSocket)  ; What happens?
      
      If serverevent=2                  ; Rawdata received (2 is described by the PB Manual)
        
        If receiveexpected>0
          received=recv_(hSocket,*receivebuffer.l+totalreceived.l,receiveexpected-totalreceived,0)
      
          If received<>#SOCKET_ERROR
            If received>0:totalreceived+received:EndIf
            If totalreceived=PeekL(*receivebuffer.l) ; Is our packet complete?
              command$=PeekS(*receivebuffer+4)       ; Get our Command-String from Memorybuffer
              anz=MyGetCommand(command$)             ; Tokanize our Command-String
              totalreceived=0                        ; Datapacket complete, reset value and wait for new one
              receiveexpected=-1                     ; Wait for new packetheader but do not execute the next part!
            
              ; Message Processing here
              
              If commands$(0)="STRG"
                ;AddGadgetItem(#ChatWindow,-1,commands$(1)+" > "+commands$(2))
                showmsg(commands$(1)+" > "+commands$(2))
              EndIf
              
              If commands$(0)="ENTR"
                ;AddGadgetItem(#ChatWindow,-1,commands$(1)+" entered the chat.")
                showmsg(commands$(1)+" entered the chat.")
              EndIf
            
            EndIf
          EndIf
        EndIf
      
        If totalreceived<3 And receiveexpected=0                            ; Receive our Packetheader till it is complete
          received=recv_(hSocket,*receivebuffer+totalreceived,4-totalreceived,0)   ; Receive TCP/IP Buffer (max. 4 Bytes)
          If received<>#SOCKET_ERROR
            If received=4
              receiveexpected=PeekL(*receivebuffer)
            EndIf        ; Completed yet?
            If received>0:totalreceived+received:EndIf                       ; Count our Received bytes (we need 4!)
            commands$(0)=""                                               ; Erase our String to avoid multihandling
          EndIf
        EndIf
              
        If receiveexpected=-1:receiveexpected=0:EndIf                     ; Ready to receive next dataheader again!!

      EndIf                             ; End RAW Data receive

      EndIf
    ProcedureReturn Result 
EndProcedure

SetWindowCallback(@window())


Repeat
    
    winevent.l=WaitWindowEvent()        ; Get Window-Event ID
    wineventgadget.l=EventGadgetID()    ; Get Gadget-Event ID
    wineventtype=EventType()            ; Get Windows Event Type
    winid=EventWindowID()               ; Get window where the event occurs
    winmenu=EventMenuID()               ; Get MenuID

    lastgadget.l=wineventgadget.l

    ; Handle Windowevents here
    
    If winevent.l=#PB_Event_Menu        ; Menuchecking for keyboard shortcuts
      If winmenu=#Returnkey
          If LCase(GetGadgetText(#Chattext))="send"
            nick$=InputRequester("Send File to user...","Please type in the nickname of user:","")
            file$=OpenFileRequester("Select file to send to "+nick$,"","*.*","")
            mysend(hSocket,"FILE@!"+nick$+"@!"+file$+"@!"+StrU(FileSize(file$),#Long)+"@!")
          EndIf
          If mysend(hSocket,"STRG@!"+GetGadgetText(#NickString)+"@!"+GetGadgetText(#Chattext)+"@!")=#SOCKET_ERROR
          showmsg("Could not send String.")
         ; AddGadgetItem(#ChatWindow,-1,"Could not send String.")
        Else
          ;AddGadgetItem(#ChatWindow,-1,GetGadgetText(#NickString)+" > "+GetGadgetText(#Chattext))
          showmsg(GetGadgetText(#NickString)+" > "+GetGadgetText(#Chattext))
          SetGadgetText(#ChatText,"")
        EndIf
      EndIf
    EndIf
    
    If winevent.l=#PB_Event_Gadget      ; Any Gadgetevent here?
      
      If wineventgadget=#Connect        ; User try to connect
        hSocket=OpenNetworkConnection(GetGadgetText(#HostString),6000)
        If hSocket=0
          MessageRequester("","Could not connect to server.",0)
        Else
          ; Connection successfull, add a Usermessage to the Window
          WSAAsyncSelect_(hSocket,hWin,#NetworkEvent,#FD_READ | #FD_Write |#FD_OOB)
          mysend(hSocket,"ENTR@!"+GetGadgetText(#NickString)+"@!")
          ;AddGadgetItem(#ChatWindow,-1,"Connected to server.")
          showmsg("Connected to server.")
          ; We are now successfully connected
        EndIf
      
      EndIf                             ; End Connect
      
      If wineventgadget=#Send
        If mysend(hSocket,"STRG@!"+GetGadgetText(#NickString)+"@!"+GetGadgetText(#Chattext)+"@!")=#SOCKET_ERROR
          AddGadgetItem(#ChatWindow,-1,"Could not send String.")
        Else
          ;AddGadgetItem(#ChatWindow,-1,GetGadgetText(#NickString)+" > "+GetGadgetText(#Chattext))
          showmsg(GetGadgetText(#NickString)+" > "+GetGadgetText(#Chattext))
          SetGadgetText(#ChatText,"")
        EndIf
      EndIf
     
      EndIf      ; End gadgetevents condition
    
   

Until winevent=#PB_Event_CloseWindow

End
Sorry for huge sources. :o)

Mike
Tranquil
Post Reply