邪恶八进制信息安全团队技术讨论组's Archiver

金州 2005-12-31 22:35

[转载]C语言设计一个Windows Socket

信息来源:ybb`s homepage

l基本概念
对程序员来说,可以把socket看成一个文件指针,只要向指针所指的文件读写数据,就可以实现双方通信。利用socket进行通信,有两种主要方式。

第一种是面向连接的流方式,两个通信的应用程序之间先要建立一种连接链路,数据才能被正确传送接收。这种方式对应的是TCP协议。特点是:通信可靠,对数据有校验和重发机制,通常用作数据文件的传输,如ftp、telnet。

第二种是无连接的数据报文方式,这时两台计算机像是把数据放在一封信里通过网络寄给对方,信在传输过程中可能会残缺不全,而且后发的信可能会先被收到,对应的是UDP协议。由于取消重发校验机制,能够达到较高的通信速率,可以用作一些对数据可靠性要求不高的通信,如实时语音,图像传送,广播信息。

在ISO的OSI网络七层协议中,WINSOCK主要负责是控制数据的输入输出,也就是传输层和网络层,屏蔽了数据链路层和物理层,给windows下的网络编程带了巨大变化。

  WINSOCK的编程特点
网络通信中,由于网络拥挤或一次发送的数据量过大等原因,经产会发生交换的数据在短时间内不能传送完,收发数据的函数因此不能返回,这种现象叫阻塞。WINSOCK对有可能阻塞的函数提供两种处理方式:

1.      阻塞方式:收发数据的函数在被调用后一直要到传送完毕或者出错才能返回,期间,除了等待网络操作的完成不能进行任何操作。用户可能会因为长时间等待而关闭主窗口。
2.      非阻塞方式:函数被调用后立即返回,当网络操作传送完成后由WINSOCK给应用程序发送一个消息通知操作完成,可以根据发送的消息传出的参数判断操作是否正常。

  WINSOCK基本的API

WSAStartup():初始化
函数原型:

int PASCAL FAR WSAStrartup(WORD wVersionRequest,LPWSADATA  lpWSAData);

windows socket由DLL形式提供,为了完成一系列初始化操作,每一个使用windows socket的应用程序必须进行WSAStartup()调用,只有完成成功的调用后才能使用socket。

wVersionRequest :欲使用的windows socket API版本,这是一个WORD类型的整数,它的高位字节定义是次版本号,低位是主版本号。

lpWSAData:指向WSDATA资料的指针。

传回值:0表示成功,失败返回其它相应结果(失败的原因)。

Socket():创建一个Socket

函数原型:

SOCKET Scoket(int af, int type, int proctocol);
该函数功能与文件操作中的fopen类似。
af是address family。一般填写AF_INET 表示是在Internet上的socket;type是socket的类型,当采用流连接方式时写SOCK_STREAM,用数据报文方式写SOCK_DGRAM。proctocol一般为0,表示对两种类型的socket分别采用默认的TCP和UDP传输协议。函数返回值是WINSOCK定义的一种数据类型SOCKET,实际上是个整形数据,创建成功时,返回WINSOCK分配给程序的socket编号,后面调用传输函数,可以把它当作指针一样引用。创建失败返回INVALID_SOCKET。

bind():为创建socket指定通信对象。

函数原型:

int bind(SOCKET s,struct sockaddr_in * name, int namelen);
成功创建socket后,就应该选定通信对象。首先是自己的程序要与网上的哪台计算机通话;其次在多任务时,该台计算机可能会有几个程序在工作,必须指定要与哪个程序通信。前者可通过网络IP来确定,后者通过端口号确定。端口号表示同一台计算机上不同的应用程序,可以在0-65535之间任选,在编制自己通信程序时,应指定端口号大于1024。TCP——21,UDP——69。
s:上一步创建好的套接字。

name:描述通信对象地址信息的结构体的指针,namelen是该结构体的长度。


struct socketadd_in{

    short  sin_family;   //一套地址族,通常设置为AF_INET(表示Internet上的socket)

    unsigned short  sin_port;  //端口号

    struct  in_addr;    //IP地址

    char  sin_zero[8];

}

//使该结构大小和SOCKADDR结构大小相同(SOCKADDR是一个无符号short型和长度为14的char型数组构成),sockadd_in加入这个数组长度也是16,目的是方便于地址操作。



IP地址in_addr的定义如下:



struct in_addr{

    union  {

       struct{

          unsigned char s_b1;

             s_b2,s_b3,s_b4;

          }  S_un_b;

       struct{

          unsigned short  s_w1, s_w2;

          }  S_un_w;

       unsigned long S_addr;

      } S_un;

};



对一个IP地址是“10.14.25.90”sockaddr_in结构中的sin_addr可以被这样几种方法赋值:

M1:

sin_addr.S_un.S_un_b.s_b1=10;

sin_addr.S_un.S_un_b.s_b2=14;

sin_addr.S_un.S_un_b.s_b3=25;

sin_addr.S_un.S_un_b.s_b4=90;

M2:

sin_addr.S_un.S_sun_w.s_w1=(14<<8)|10;

sin_addr.S_un.S_sun_w.s_w2=(90<<8)|25;

M3:

sin_addr.S_un.S_addr=(90<<24)|(25<<16)|(14<<8)|10;



listen():设置等待连接状态

函数原型:

int listen(SOCKET s, int backlog);



对于服务器的程序,当申请到socket,并指定通信对象为INADDR_ANY之后,就应该等待一个客户机的程序要求连接,listen()就是把一个socket设置这种状态的函数。backlog表示等待连接队列长度,可取1-5,如果服务器已经和其它客户程序连接,则后来这个连接被放在队列中,等待服务器空闲的时候连接。当队列达到指定长度backlog,再来连接会被拒绝。



accept():接收连接请求。

函数原型:

SOCKET accept(SOCKET s, struct sockaddr_in *  addr , int * addrlen);



接收到连接后,会为这个连接建立一个新的socket用来与对方通信,并把它作为返回值,新建的socket与原来的socket有相同的特性,包括端口号,而原来的socket被释放,用于等待其它连接请求。新的SOCKET才是与客户端通信的实际的SOCKET。所以参数中SOCKET称为监听SOCKET,负责连接,而accpet返回的SOCKET成为会话SOCKET。addr和addrlen返回客户机的sockaddr_in结构体。



connect():请求建立连接。适用于客户机。

函数原型:

int connect (SOCKET s,struct sockaddr_in * name, int namlen);



send()/recv():发送接收数据

函数原型:

int send(SOCKET s,char *buf, int len, int flags);

int recv(SOCKET s,char *buf, int len, int flags);



s是连接的socket,buf和len是发送接收的数据包及其长度。flags一般为0。recv()实际上是接收send()的数据包,当读到的数据字节少于规定接收的数目时,就把数据全部接收,返回实际字节数。当多于规定值时,流方式下,剩余字节由下一个recv()读出;在数据报文方式下,多余数据将被丢弃,这两个函数出错返回SOCKET_ERROR。



数据报文方式通信的socket,由于事先不建立连接,所以跳过了connect()而直接调用以下方式:



int recvfrom (SOCKET s,char *buf, int len, int flags,struct sockaddr_infrom,int *fromlen);

int sendto  (SOCKET s, char *buf,  int len,  int flags, struct sockaddr_into, int *tolen);



from,fromlen,to,tolen分别表示接收发送数据对象。



closesocket():关闭socket

函数原型:

closesocket(SOCKET s);



通信结束,关闭socket。

页: [1]
© 1999-2008 EvilOctal Security Team