zoukankan      html  css  js  c++  java
  • Delphi socket() 函数的应用


    socket()系统调用,带有三个参数:
        1、参数domain指明通信域,如PF_UNIX(unix域),PF_INET(IPv4),
          PF_INET6(IPv6)等
        2、type指明通信类型,最常用的如SOCK_STREAM(面向连接可靠方式,
          比如TCP)、SOCK_DGRAM(非面向连接的非可靠方式,比如UDP)等。
        3、参数protocol指定需要使用的协议。虽然可以对同一个协议
          家族(protocol family)(或者说通信域(domain))指定不同的协议
          参数,但是通常只有一个。对于TCP参数可指定为IPPROTO_TCP,对于
          UDP可以用IPPROTO_UDP。你不必显式制定这个参数,使用0则根据前
          两个参数使用默认的协议。
     
    sa:SOCKADDR_IN;
    sa.sin_family:=PF_INET;
      sa.sin_port:=htons(lisport);
      sa.sin_addr.S_addr:=INADDR_ANY;//---------dcc-----htonl(INADDR_ANY);  //INADDR_ANY,表示本地计算机的默认IP地址
      salen:=sizeof(sa);
      //******************************************************************************
        { sin_family指代协议族,在socket编程中只能是AF_INET ,PF_INET
          sin_port存储端口号(使用网络字节顺序)
          sin_addr存储IP地址,使用in_addr这个数据结构
          s_addr按照网络字节顺序存储IP地址
          sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。
        }
    int bind ( SOCKET s , const struct sockaddr FAR *addr , int namelen );
        [参数]
        s - 指向用Socket函数生成的Socket Descrīptor
        addr - 指向Socket地址的指针
        namelen - 该地址的长度.
        [返回值]
        当函数成功调用时返回0
        调用失败时返回 SOCKET_ERROR
    if bind(lissocket,sa,sizeof(sa))=SOCKET_ERROR then
    begin
        closesocket(lissocket);
        DebugMessage('无法打开端口:'+inttostr(lisport));
        exit;
    end;
    listen(lissocket,200);
        //**********************************************
         {socket 套接字,网络编程必用的
          listen ()监听从服务器传来的接收数据
          listen ()创建一个套接口并监听申请的连接.}
        //*******************************************
    accept()
     acceptsocket:=accept(lissocket,@sa,@salen); //AcceptSocket 是一个阻塞方法,它返回可用来发送和接收数据的 Socket。
        DebugMessage('连接成功!');
        if acceptsocket=INVALID_SOCKET then
        begin
          DebugMessage('接受Socket失败!');
          continue;
        end;
    //**************&&&&&&&&&&&&&&&&&&%%%%%%%%%%%%%%%%%%%%%%%%  源码
    unit Listenthread;
    interface
    uses
      Classes,messages,windows,winsock,stdctrls,Sysutils;
    type
      //线程的声明
      TListenThread = class(TThread)
      private
        { Private declarations }
        lissocket:Tsocket;
        lisport:integer;
        str:string;
        procedure AddMes;
        procedure DebugMessage(mes:string);
      protected
        procedure Execute; override;  //线程执行过程
       
      public
        constructor CreateIt(port:integer); //创建线程端口
        destructor  destroy;override;  //结束线程
      end;
    implementation
    uses main,UnitSocketRead,DataUnit ;

    //监听线程的构造方法
    constructor TlistenThread.CreateIt(port:integer); //创建端口
    begin
      inherited create(true);
      lisport:=port;
      FreeOnTerminate:=true;
      resume; //******唤醒线程  重(新)开(始),再继续;恢复;收回;【微软】继续执行 挂起的线程重新执行。
    end;

    destructor TlistenThread.destroy;
    begin
      if lissocket<>INVALID_SOCKET then
      begin
        //shutdown(lissocket,SD_BOTH);//中断连接,其实连接还存在。
        closesocket(lissocket);   //*********CloseSocket() 是用来关闭一个 Socket 的!
        DebugMessage('Close Socket');
      end;
      inherited destroy;
    end;
    procedure TlistenThread.Execute;
    var   acceptsocket:Tsocket;
          sa:SOCKADDR_IN;
          salen:integer;
          tempthreadread:ThreadSocketRead;
    begin
      { Place thread code here }
      Lissocket:=socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
      //***********************************************************************************
      {socket()系统调用,带有三个参数:
        1、参数domain指明通信域,如PF_UNIX(unix域),PF_INET(IPv4),
          PF_INET6(IPv6)等
        2、type指明通信类型,最常用的如SOCK_STREAM(面向连接可靠方式,
          比如TCP)、SOCK_DGRAM(非面向连接的非可靠方式,比如UDP)等。
        3、参数protocol指定需要使用的协议。虽然可以对同一个协议
          家族(protocol family)(或者说通信域(domain))指定不同的协议
          参数,但是通常只有一个。对于TCP参数可指定为IPPROTO_TCP,对于
          UDP可以用IPPROTO_UDP。你不必显式制定这个参数,使用0则根据前
          两个参数使用默认的协议。}
      //******************************************************************************
      if lissocket=INVALID_SOCKET then
      begin
        DebugMessage('Create Socket Error');
        exit;
      end;
      DebugMessage('Create Socket!');  //调用本单元的 DebugMessage方法   显示成功创建套接字
      sa.sin_family:=PF_INET;
      sa.sin_port:=htons(lisport);
      sa.sin_addr.S_addr:=INADDR_ANY;//---------dcc-----htonl(INADDR_ANY);  //INADDR_ANY,表示本地计算机的默认IP地址
      salen:=sizeof(sa);
      //******************************************************************************
        { sin_family指代协议族,在socket编程中只能是AF_INET ,PF_INET
          sin_port存储端口号(使用网络字节顺序)
          sin_addr存储IP地址,使用in_addr这个数据结构
          s_addr按照网络字节顺序存储IP地址
          sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。
        }
       { int bind ( SOCKET s , const struct sockaddr FAR *addr , int namelen );
        [参数]
        s - 指向用Socket函数生成的Socket Descrīptor
        addr - 指向Socket地址的指针
        namelen - 该地址的长度.
        [返回值]
        当函数成功调用时返回0
        调用失败时返回 SOCKET_ERROR
          }
      //***********************************************************************************
      if bind(lissocket,sa,sizeof(sa))=SOCKET_ERROR then
      begin
        closesocket(lissocket);
        DebugMessage('无法打开端口:'+inttostr(lisport));
        exit;
      end;
      DebugMessage('listen on port:'+inttostr(lisport)); //调用本单元的 DebugMessage方法    显示连接的端口号
      listen(lissocket,200);
        //**********************************************
         {socket 套接字,网络编程必用的
          listen ()监听从服务器传来的接收数据
          listen ()创建一个套接口并监听申请的连接.}
        //*******************************************
      while not terminated do
      begin
        acceptsocket:=accept(lissocket,@sa,@salen); //AcceptSocket 是一个阻塞方法,它返回可用来发送和接收数据的 Socket。
        DebugMessage('连接成功!');
        if acceptsocket=INVALID_SOCKET then
        begin
          DebugMessage('接受Socket失败!');
          continue;
        end;
        //调用 UnitSocketRead 方法块中的 ThreadSocketRead.CreateIt 方法 并且同时调用datamoudle的数据库连接控件的连接语句。
        tempthreadread:=ThreadSocketRead.CreateIt(acceptsocket,Datamodule1.ADOConnection1.ConnectionString);
        if tempthreadread<>nil then
        begin
          str:='New thread:'+IntToStr(tempthreadread.threadid);
          synchronize(AddMes);                    //synchronize 时间同步   调用方法本模块的 AddMes方法
        end
        else
        begin
          closesocket(acceptsocket);
          DebugMessage('创建执行线程失败!');   //调用本单元的 DebugMessage方法
        end;

      end;
      closesocket(lissocket);  //一个关闭套接口的方法
    end;
    procedure TlistenThread.AddMes;  //显示当前的时间 和 要显示的信息
    begin
      if  not terminated then    //terminated  终结
         FormMain.Memo.Lines.Add(FormatDatetime('hh:mm:ss',Now)+'-*-'+Str);
    end;
    procedure TListenThread.DebugMessage(mes:string);  //获得要显示的信息 并将信息作为参数传递给AddMes方法
    begin
       if  gdebug then
       begin
         Str:=mes;
         synchronize(AddMes);  //synchronize 时间同步   调用方法本模块的 AddMes方法
       end;
    end;
    end.
     
     
     
     
     
     
     
     
     
     
     
     



  • 相关阅读:
    响应式笔记(1)
    javascript复制文章加版权声明代码
    div的水平和垂直居中
    javascript随机打乱数组
    javascript操作字符串的方法
    《Javascript高级程序设计》读书笔记(1-3章)
    一个将 footer 保持在底部的最好方法
    Python内置的字符串处理函数整理
    c c++怎么判断一个字符串中是否含有汉字
    shell的if判断
  • 原文地址:https://www.cnblogs.com/zhangzhifeng/p/3254546.html
Copyright © 2011-2022 走看看