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.