Delphi实现winsock编程之二(套接字的建立绑定侦听以及连接)

来源:互联网 发布:网络统考信息管理 编辑:程序博客网 时间:2024/05/18 08:04

以面向连接的网络协议为例,使用套接字进行通信的过程如下图

先总结服务器端步骤

  • 1建立套接字
  • 2绑定连接
  • 3端口侦听
  • 4调用accept等待客户端连接
  • 5如有连接产生新的套接字,原套接字继续侦听。
  • 6新套接字与客户端进行通信(接受和发送数据)
  • 7如果通信完毕,请关闭新套接字。
  • 8主动关闭套接字

客户端相对而言比较简单

  1. 1建立套接字
  2. 2连接服务器端
  3. 3与服务器端口通信(接受和发送数据)
  4. 4发送完毕关闭套接字

下面以静海老师《深入Delphi6网络编程》书第六章简单文件接收器为例看服务器端代码:

procedure TFrmMain.BitListenClick(Sender: TObject);var     ca:SOCKADDR_IN;begin        Server:=Socket(PF_INET, SOCK_STREAM, IPPROTO_IP);  //第一步创建端口        if Server=INVALID_SOCKET then                begin                    StaBar.SimpleText:='创建接收Socket错误!' ;                    Exit;                end;        ca.sin_family:=PF_INET;        ca.sin_port:=htons(StrToInt(Trim(OtherPort.Text)));        ca.sin_addr.S_addr:=INADDR_ANY;        if bind(Server,ca,sizeof(ca))=SOCKET_ERROR then   //第二部绑定                begin                StaBar.SimpleText:='绑定接收端Socket错误!请更改接收端口!';                closesocket(Server);                Exit;                end        else                StaBar.SimpleText:='绑定接收端Socket成功!';        listen(Server,5);  //第三步侦听        BitListen.Enabled:=False;        BitStop.Enabled:=True;end;
下面详细解释前三步winsock的实现
第一步建立套接字
socket函数定义:

function socket(af, Struct, protocol: Integer): TSocket; stdcall;

返回类型为Tsocket,其实也就是一个整数类型,用来标识套接字对象。

输入参数af 表示地址族,目前只支持IPv4,所以只能设改值为AF_INET。

Struct 套接字类型,如果是TCP/IP应将字段设为SOCK_STREAM,如果使用UDP/IP则应设为SOCK_DGRAM。

protocol协议,如果使用TCP协议应设为IPPROTO_TCP,如果使用UDP则设为IPPROTO_UDP。

第二步绑定端口

socket绑定函数定义:

function bind(s: TSocket; var addr: TSockAddr; namelen: Integer): Integer; stdcall;

绑定套接字比建立套接字复杂

s是前面建立的TSocket。

namelen是前面addr的长度。

addr是与寻址相关的信息。类型为TsockAddr,详细定义如下:

  sockaddr_in = record    case Integer of      0: (sin_family: u_short;          sin_port: u_short;          sin_addr: TInAddr;          sin_zero: array[0..7] of Char);      1: (sa_family: u_short;          sa_data: array[0..13] of Char)  end;  TSockAddrIn = sockaddr_in;  TSockAddr = sockaddr_in;
 sin_family与第一步中af协议族定义相同。
 sin_port为绑定的端口号。2个字节长度,注意高低字节的排布。
 sin_addr的详细定义如下:
  in_addr = record    case integer of      0: (S_un_b: SunB);      1: (S_un_w: SunW);      2: (S_addr: u_long);  end;  TInAddr = in_addr;

看上去比较复杂,其实说到底就是一个存储IP地址的32位的整数。

sin_zero没有真实含义,填充0保证sockaddr_in的长度为16个字节。以便dll调用

回过来看第二步之前的准备代码:

//准备协议族        ca.sin_family:=PF_INET;//准备端口,注意字节的排列需要安装网络定义,所以调用htons函数ca.sin_port:=htons(StrToInt(Trim(OtherPort.Text)));//绑定所有网卡的IP地址上ca.sin_addr.S_addr:=INADDR_ANY;

第三步侦听

函数定义如下

function listen(s: TSocket; backlog: Integer): Integer; stdcall;

backlog为指定被搁置连接的最大队列长度。

前面的散步只是准备了侦听,并没有实际的接受连接。至于如何接受连接并进行相关处理,会在后面内容继续介绍。

原创粉丝点击