FreeBasic编写的PowerBasic内置网络函数

利用freebasic编写了一遍powerbasic中内置的网络函数,为的是保留pb编程风格。

首先创建一个pb_winsock.bi库文件。

1、文件头

#include once "win/winsock2.bi"

#define TCP_ACCEPT  WM_USER + 4093 
#define TCP_ECHO  WM_USER + 4094 

#define LRCF CHR(10,13)
#define DEFAULT_BUFLEN 512

const NewLine = !"\r\n"

declare function HOST_ADDR ( hostname as string ) as ulong
declare function HOST_NAME ( byval ip as ulong ) as string
declare function TCP_OPEN ( srvc as string, address as string ) as SOCKET
declare function TCP_OPEN_PORT ( byval server_prot as long, server_addr as string ) as SOCKET
declare function TCP_OPEN_SERVER ( byval server_ip as long, byval server_prot as long ) as socket
declare function TCP_ACCEPTS ( byval hSocket as SOCKET ) as SOCKET
declare function TCP_NOTIFY ( byval hSocket as SOCKET, byval hWnd as HWND, byval wMsg as u_int, byval lEvent as long ) as long
declare sub TCP_RECV ( byval hSocket as SOCKET, byval strlen as integer, sBuffer as string )
declare sub TCP_SEND ( byval hSocket as SOCKET, sBuffer as string )
declare sub TCP_PRINT ( byval hSocket as SOCKET, sBuffer as string )
declare sub TCP_CLOSE ( byval hSocket as SOCKET )
declare function TCP_GetIP ( byval hSocket as SOCKET ) AS string
declare function TCP_GetProt ( byval hSocket as SOCKET ) AS string

2、函数定义

'======================================================================
' #INCLUDE ONCE "WinSock2.bi"
' Translate a host name into a corresponding IP address
'======================================================================
function HOST_ADDR ( hostname as string ) as ulong
    function = inet_addr ( hostname )
end function

'======================================================================
' #INCLUDE ONCE "WinSock2.bi"
' Translate an IP address into a corresponding host name
'======================================================================
function HOST_NAME ( byval ip as ulong ) as string
    dim cin as IN_ADDR
    cin.S_un.S_addr_ = ip
    function = *inet_ntoa ( cin )
end function

'======================================================================
' #INCLUDE ONCE "WinSock2.bi"
' Enable an application to communicate with a TCP/IP client
' srvc$ A service name takes the form of "http", "smtp", or "ftp", etc. 
' address$ As a client, address$ identifies the address to connect with.
'======================================================================
function TCP_OPEN ( srvc as string, address as string ) as SOCKET
    dim hSocket as SOCKET
    dim wsaData as WSADATA
    dim iResult as LONG
    dim ia as in_addr
    dim client as sockaddr_in
    dim hostentry as hostent ptr
    dim bytes as integer
    dim ip as integer
    
    WSAStartup ( MAKEWORD ( 2, 2 ), @wsaData )
    hSocket = opensocket ( AF_INET, SOCK_STREAM, IPPROTO_TCP )
    
    IF hSocket = INVALID_SOCKET THEN
        closesocket ( hSocket ) 
        WSACleanup ( )
        function = INVALID_SOCKET
        exit function
    end if

    if srvc = "http" then
        client.sin_port = htons ( 80 )
    end if
    if srvc = "smtp" then
        client.sin_port = htons ( 25 )
    end if
    if srvc = "ftp" then
        client.sin_port = htons ( 21 )
    end if

    ia.S_addr = inet_addr( address )
    if ( ia.S_addr = INADDR_NONE ) then        
        hostentry = gethostbyname ( address )
        if ( hostentry = 0 ) then
            closesocket ( hSocket ) 
            WSACleanup ( )
            function = INVALID_SOCKET
            exit function
        end if
        ip = *cast ( integer ptr, *hostentry->h_addr_list )
        else
            ip = ia.S_addr
    end if
    
    client.sin_family      = AF_INET
    client.sin_addr.s_addr = ip
    iResult = connect ( hSocket , Cptr ( SOCKADDR ptr, @client ), SIZEOF ( client ) )

    if iResult = SOCKET_ERROR then
        closesocket ( hSocket ) 
        WSACleanup ( )
        function = INVALID_SOCKET
        exit function
    end if
    
    function = hSocket
end function

'======================================================================
' #INCLUDE ONCE "WinSock2.bi"
' Enable an application to communicate with a TCP/IP client
' using the TCP protocol over Winsock
'======================================================================
function TCP_OPEN_PORT ( byval server_prot as long, server_addr as string ) as SOCKET
    dim hSocket as SOCKET
    dim wsaData as WSADATA
    dim iResult as LONG
    dim service as sockaddr_in
    
    WSAStartup ( MAKEWORD ( 2, 2 ), @wsaData )
    hSocket = opensocket ( AF_INET, SOCK_STREAM, IPPROTO_TCP )
    
    IF hSocket = INVALID_SOCKET THEN
        closesocket ( hSocket ) 
        WSACleanup ( )
        function = hSocket
        exit function
    end if
    
    service.sin_family      = AF_INET
    service.sin_addr.s_addr = inet_addr ( server_addr )
    service.sin_port        = htons ( server_prot )
    iResult = connect ( hSocket , Cptr ( SOCKADDR ptr, @service ), SIZEOF ( service ) )
    
    if iResult = SOCKET_ERROR then
        closesocket ( hSocket ) 
        WSACleanup ( )
        function = INVALID_SOCKET
        exit function
    end if
    
    function = hSocket
end function   

'======================================================================
' #INCLUDE ONCE "WinSock2.bi"
' Enable an application to communicate with a TCP/IP server
' using the TCP protocol over Winsock
'======================================================================
function TCP_OPEN_SERVER ( byval server_ip as long, byval server_prot as long ) as socket
    dim hSocket as SOCKET
    dim wsaData as WSADATA
    dim service as sockaddr_in 
    dim iResult as long
    
    WSAStartup ( MAKEWORD ( 2, 2 ), @wsaData )
    hSocket = opensocket ( AF_INET, SOCK_STREAM, IPPROTO_TCP )
    if hSocket = INVALID_SOCKET then
        closesocket ( hSocket )
        WSACleanup ( )
        function = hSocket
        exit function
    end if 
    
    service.sin_family          = AF_INET
    'service.sin_addr.S_un.S_addr_ = htonl ( INADDR_ANY )'inet_addr ( server_addr )
    service.sin_addr.s_addr = server_ip
    service.sin_port             = htons ( server_prot )
    iResult = bind ( hSocket , Cptr ( SOCKADDR ptr, @service ), sizeof ( service ) )
    if iResult = 0 then
       iResult = listen ( hSocket, SOMAXCONN )
       else
            closesocket ( hSocket )
            WSACleanup ( )
    end if

    function = hSocket
end function

'======================================================================
' #INCLUDE ONCE "WinSock2.bi"
' Accept an incoming request for communication from a specified TCP/IP port
'======================================================================
function TCP_ACCEPTS ( byval hSocket as SOCKET ) as SOCKET
   dim nSocket as SOCKET
   dim clientsocket as SOCKADDR_IN
   dim lens as ulong = sizeof ( SOCKADDR )   
   nSocket = accept ( hSocket, Cptr ( SOCKADDR ptr, @clientsocket ), @lens )
   function = nSocket
end function

'======================================================================
' #INCLUDE ONCE "WinSock2.bi"
' Designate which TCP/IP events will generate a notification message
' WSACreateEvent ( )
' rc = WSAEventSelect(s, hEventObject, FD_READ or FD_WRITE)
' TCP_NOTIFY hSocket, hWnd, TCP_ACCEPT, FD_ACCEPT
'======================================================================
function TCP_NOTIFY ( byval hSocket as SOCKET, byval hWnd as HWND, byval wMsg as u_int, byval lEvent as long ) as long
    dim rc as long 
    rc = WSAAsyncSelect ( hSocket, hWnd, 0, 0 )
    rc = WSAAsyncSelect ( hSocket, hWnd, wMsg, lEvent )
    function = rc
end function

'======================================================================
' #INCLUDE ONCE "WinSock2.bi"
' Receive data from a specified TCP/IP port
'======================================================================
sub TCP_RECV ( byval hSocket as SOCKET, byval strlen as integer, sBuffer as string )
    dim bytes as integer
    dim s as string
    dim recvbuffer as zstring ptr
    recvbuffer = Allocate ( strlen+1 )
    's = space ( strlen )
    do
        bytes = recv ( hSocket, recvbuffer, strlen+1, 0 )
        s = *recvbuffer
        sBuffer = sBuffer + s
        ZeroMemory ( recvbuffer, strlen+1 )
    loop while ( bytes > 0 ) or ( len( s ) > 0 ) or not( SOCKET_ERROR )
    Deallocate recvbuffer
end sub 

'======================================================================
' #INCLUDE ONCE "WinSock2.bi"
' Receive a line of text from a specified TCP/IP port.
'======================================================================
sub TCP_LINE_INPUT ( byval hSocket as SOCKET, sBuffer as string )
    dim bytes as integer
    dim idx as integer
    dim s as string
    dim recvbuffer as zstring ptr
    recvbuffer = Allocate ( 512 )
    idx = -1
    do
        bytes = recv ( hSocket, recvbuffer, 512, 0 )
        s = *recvbuffer
        idx = InStr ( s, LRCF )
        if idx > 0 then
            sBuffer = sBuffer + Left ( s, idx )
            else
            sBuffer = sBuffer + s
        end if
        ZeroMemory ( recvbuffer, 512 )
    loop while idx<0 or ( bytes > 0 ) or ( len( s ) > 0 ) or not( SOCKET_ERROR )
    Deallocate recvbuffer
end sub

'======================================================================
' #INCLUDE ONCE "WinSock2.bi"
' Write a string to a nominated TCP/IP port
'======================================================================
sub TCP_SEND ( byval hSocket as SOCKET, sBuffer as string )
    send ( hSocket, sBuffer, len ( sBuffer ) + 1, 0 )
end sub

'======================================================================
' #INCLUDE ONCE "WinSock2.bi"
' Write a string to a nominated TCP/IP port
'======================================================================
sub TCP_PRINT ( byval hSocket as SOCKET, sBuffer as string )
    sBuffer = sBuffer + NewLine
    send ( hSocket, sBuffer, len ( sBuffer ) + 1, 0 )
end sub

'======================================================================
' #INCLUDE ONCE "WinSock2.bi"
' Close a previously opened TCP/IP port
'======================================================================
sub TCP_CLOSE ( byval hSocket as SOCKET )
    closesocket ( hSocket )
    WSACleanup ( )
end sub

'----------------------------------------------------------
' 返回客户端IP
'----------------------------------------------------------
function TCP_GetIP ( byval hSocket as SOCKET ) as string
   dim sock_sa as SOCKADDR_IN 
   dim lpszIP as zstring ptr
   dim namelen as long
   
   namelen = SIZEOF ( sock_sa )
   if getpeername ( hSocket, Cptr ( SOCKADDR ptr, @sock_sa ), @namelen ) <> SOCKET_ERROR then
      lpszIP = inet_ntoa ( sock_sa.sin_addr )
      function = *lpszIP
   end if
end function

'----------------------------------------------------------
' 返回客户端port
'----------------------------------------------------------
function TCP_GetProt ( byval hSocket as SOCKET ) as string
   dim sock_sa AS sockaddr_in
   dim namelen as long
   namelen = sizeof ( sock_sa )
   if getpeername ( hSocket, Cptr ( SOCKADDR ptr, @sock_sa ), @namelen ) <> SOCKET_ERROR then
      function = str ( ntohs ( sock_sa.sin_port ) + 1 )
   end if
end function 

3、函数程序中应用实例。(服务端)

function WindowProc ( byval hWnd as HWND, byval wMsg as UINT, byval wParam as WPARAM, byval lParam as LPARAM ) as LRESULT
    dim wmId as integer
    dim wmEvent as integer
    dim ListenSocket as SOCKET = INVALID_SOCKET
    dim AcceptSocket as SOCKET = INVALID_SOCKET

    select case( wMsg )
       case TCP_ACCEPT
           wmEvent = LOWORD ( lParam )
           ListenSocket = cast ( socket, wParam )
           select case wmEvent
              case FD_ACCEPT
                  AcceptSocket = TCP_ACCEPTS ( ListenSocket )
                  TCP_NOTIFY AcceptSocket, hWnd, TCP_ECHO, FD_READ OR FD_WRITE OR FD_CLOSE
                  
           end select
           function = 1

       case TCP_ECHO
           dim sendBuf as string * 1024
           dim receiveBuf as string '* 1024
           dim sBuffer as string
           wmEvent = LOWORD ( lParam )
           AcceptSocket = cast ( socket, wParam )
           select case wmEvent
              case FD_READ
                  'do
                     TCP_RECV AcceptSocket, 1024, receiveBuf
                   '  sBuffer = sBuffer + receiveBuf
                  'loop while receiveBuf = " "                 
                 MessageBox ( hWnd, receiveBuf, "Server 提示窗口 ( %FD_READ )", MB_OK )
 
              case FD_WRITE
                  sendBuf = "welcome to bejing" + "  " + TCP_GetIP ( AcceptSocket )
                  TCP_SEND ( AcceptSocket, sendBuf )
                  'MessageBox ( hWnd, sendBuf, "Server 提示窗口 ( %FD_WRITE )", MB_OK ) 
                  
              case FD_CLOSE
                 TCP_CLOSE ( AcceptSocket ) 
                  
           end select
           function = 1
        
       case WM_COMMAND
           wmId       = loword ( wParam )
           wmEvent = hiword ( wParam ) 
           select case ( wmId )
               case IDC_BUTTON1
                   if wmEvent = BN_CLICKED or wMsg = 1 then                       
                       dim ip as ulong = HOST_ADDR ( ServerAddress )
                       ListenSocket = TCP_OPEN_SERVER ( ip, ServerPort )
                       'MessageBox ( hWnd, str ( ListenSocket ), "Server 提示窗口", MB_OK )

                       if ListenSocket = INVALID_SOCKET then
                           TCP_CLOSE ( ListenSocket )
                           function = 0
                           exit function
                       end if
                       
                       TCP_NOTIFY ListenSocket, hWnd, TCP_ACCEPT, FD_ACCEPT                     
                   end if
                
               case IDC_BUTTON2                  
                   
           end select
           
        case WM_CLOSE
            TCP_CLOSE ( ListenSocket )
            DIALOG_END hWnd 
            exit function
            
        case WM_DESTROY
            TCP_CLOSE ( ListenSocket )
            DIALOG_END hWnd
            exit function
            
    end select                                         
    function = DefWindowProc ( hWnd, wMsg, wParam, lParam )                                             
end function                      

4、函数程序中应用实例。(客户端)

function WindowProc ( byval hWnd as HWND, byval wMsg as UINT, byval wParam as WPARAM, byval lParam as LPARAM ) as LRESULT
    dim wmId as integer
    dim wmEvent as integer
    dim wmError as long
    dim clientSocket as SOCKET 
    
    select case( wMsg )          
       case TCP_ACCEPT 
           dim receiveBuf as string
           dim sBuffer as string
           wmEvent = LOWORD ( lParam )
           wmError = HIWORD ( lParam )          
           clientSocket = cast ( socket, wParam )

          select case wmEvent                  
              case FD_READ
                  TCP_RECV clientSocket, 256, receiveBuf  
                  MessageBox ( hWnd,  receiveBuf, "Client 提示窗口", MB_OK )
                   
              case FD_WRITE
                  receiveBuf = "hello, this is client"
                  TCP_SEND clientSocket, receiveBuf
                  
              case FD_CLOSE      
                  TCP_CLOSE ( clientSocket )

          end select
          
       case WM_COMMAND
           wmId       = loword ( wParam )
           wmEvent = hiword ( wParam ) 
           select case ( wmId )
               case IDC_BUTTON1
                   if wmEvent = BN_CLICKED or wMsg = 1 then                       
                       clientSocket = TCP_OPEN_PORT ( ServerPort, ServerAddress )
                       TCP_NOTIFY clientSocket, hWnd, TCP_ACCEPT, FD_READ OR FD_WRITE OR FD_CLOSE                     
                   end if
                
               case IDC_BUTTON2
                   
                   
           end select
           
        case WM_CLOSE
            TCP_CLOSE ( clientSocket )
            DIALOG_END hWnd 
            exit function
            
        case WM_DESTROY
            TCP_CLOSE ( clientSocket )
            DIALOG_END hWnd
            exit function
            
    end select                                         
    function = DefWindowProc ( hWnd, wMsg, wParam, lParam )                                             
end function 

结语:由于编程水平有限,难免代码中所有瑕疵,大家可以在借鉴过程中加以修正完善,再次仅仅起到抛砖引玉的目的,与basic爱好者相互交流学习。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值