WinSocket编程
默认分类 2009-12-07 10:33:56 阅读164 评论字号:
什么是Socket
接触网络编程当然要了解SocketSocket(套接字)是一种网络编程接口,Socket提供了很多灵活的函数,帮助程序员写出高效的网络应用。Socket分为BSD UNIXwindows两个版本。
win32socket编程聊天室基本流程平台上的Winsock编程都要经过下列基本步骤:
定义变量——获得Winsock版本——加载Winsock——初始化——创建套接字——设置套接字——关闭套接字——卸载Winsock
使用winsock2 API编程,必须包含头文件winsock2.h (链接环境WS2_32.LIB),头文件winsock.hWSOCK32.LIB)是为了兼容winsock1程序时使用的,另外mswsock.hMSWSOCK.DLL)是微软的扩展类,用于开发高性能的winsock程序。
准备好后,你就可以着手建立你的第一个网络程序了。
二,          Socket编程的基本过程
Socket通信分为面向连接的通信(TCP)和面向无连接的通信(UDP),通信流程如下:
                     
                    面向连接的通信
                无连接的通信
1Winsock初始化和结束
每一个winsock应用程序必须首先加载相应的winsock dll版本。方法是调用:
int WSAStartup(
    WORD wVersionRequested,    库版本,高字节副版本,低字节主版本
    LPWSADATA lpWSAData        结构指针,函数自动填充该结构。
);    函数调用成功返回0
可以用宏MAKEWORD(x, y)用来指定第一个参数的值
2,建立套接字
套接字是传输提供者的一个句柄。
SOCKET socket (
    int af,         
    int type,       
    int protocol      IPPROTO_TCP IPPROTO_UDP 0(如果不想指定)
)
;
第一个参数指定通信协议的协议族,AF_INET(IPv4) AF_INET6(IPv6)(因为Socket是网络编程接口而不是一个协议,它使用流行的网络协议(TCP/IPIPX)为应用程序提供的一个编程接口。)
第二个参数指定要创建的套接字的类型。SOCK_STREAM(TCP流套接字), SOCK_ DGRAM(UDP 数据包套接字)SOCK_RAW(原始套接字)
第三个参数指定应用程序所指定应用程序所使用的通信协议。
函数成功返回套接字描述符,失败返回INVALID_SOCKET
3,配置套接字
当创建一个套接字后,再进行网络通信之前,必须先配置Socket。面向连接的客户端Socket通过调用connect函数在Socket数据结构中保存地址和远端信息。无连接客户端,服务端以及面向连接Socket的服务端,通过调用bind函数来配置本地信息。
int bind(
    SOCKET                    s,                创建的套接字
    const struct sockaddr FAR* name,      指向地址缓冲区的指针
    int                        namelen    地址缓冲区的大小
);
成功返回0,失败返回SOCKET_ERROR
当创建一个套接字后,套接字数据结构中有一个默认的IP地址和默认的端口号。一个服务程序必须调用bind函数来给其绑定一个IP地址和一个特定的端口号。
第二个参数指定一个sockaddr结构定义如下:
struct sockaddr {
        u_short    sa_family;
        char      sa_data[14];
};
我们通常使用另外一个等价的地址结构:
struct sockaddr_in {
        short  sin_family;
        u_short sin_port;
        struct  in_addr sin_addr;
        char    sin_zero[8];
};
其中sin_family是通信协议族,
sin_port
指明端口号,
sin_addr
结构中有一个字段s_addr,表示IP地址,该字段是一个整数,
一般用函数inet_addr把点分字符串形式的IP地址转化成unsigned long型的整数值。
如果指定为htonl(INADDR_ANY),那么无论哪个网段上的客户机都能与该服务器通信,
否则,只有与指定IP地址处于同一网段上的客户机能与该服务器通信。
sin_zero[8]
为填充,使两个结构大小相同。
有一些细节学要说明:
  在计算机把IP地址和端口号指定成多字节时,这个数是按主机字节host-byte)顺序表
示的,不同的处理器对数的表示方法有大头big-endian——最有意义的字节到最无意义的字节)和小头little-endian)两种形式。但是如果在网络上指定IP地址和端口号时,必须按照big-endian 的形式,一般称之为网络字节network-byte)顺序。
以下几个函数将主机字节顺序转换成网络字节顺序:
u_long htonl(u_long hostlong);
int WSAHtonl(
    SOCKET s,
    u_long hostlong,
    u_long FAR * lpnetlong              通过指针返回网络字节顺序的4个字节的数
);
u_short htons(u_short hostshort);
int WSAHtons(
    SOCKET s,
    u_short hostshort,
    u_short FAR * lpnetshort        通过指针返回网络字节顺序的2个字节的数
);
以下几个函数将网络字节顺序转换成主机字节顺序:
u_long ntohl(u_long netlong);
int WSANtohl(
    SOCKET s,
    u_long netlong,
    u_long FAR * lphostlong
);
u_short ntohs(u_short netshort);
int WSANtohs(
    SOCKET s,
    u_short netshort,
    u_short FAR * lphostshort
);
4,实现功能
1      服务器端: 需要对绑定的端口进行侦听,函数原型如下
     
int listen (
  SOCKET
s
  int
backlog
);
 
Backlog
是客户连接请求队列的最大数量,而不是客户机连接的数量限制。
处于侦听的套接字将维护一个客户连接请求队列。
 
该函数执行成功返回0,失败返回
SOCKET_ERROR
    此外,需要从连接请求队列中取出最前面的一个客户请求,需要用到accept()函数:
       
SOCKET accept (
  SOCKET
s
,                 
  struct sockaddr FAR*
addr
,
  int FAR*
addrlen         
);
该函数创建一个新的套接字来与客户套接字建立通信,如果连接成功,就返回新建的套接字描述符,
以后与客户通信的就是该套接字,而侦听套接字则继续接受新的连接;如果失败就返回
INVALID_SOCKET
第一个参数是侦听套接字
第二个套接字用来返回新创建的套接字的地址结构
第三个套接字返回地址结构的长度
2      客户端:
connect函数是客户机建立与远程服务器连接而使用的。
int connect (
  SOCKET
s
,                       
  const struct sockaddr FAR*
name
,
  int
namelen                     
);
5,数据传输
      收发数据时网络编程的一切在这里我们只讨论同步函数sendrecv
不讨论异步函数WSASendWSARecv
数据发送要用到send函数,原型如下:
int send(
    SOCKET s,
    const char FAR * buf,    发送数据缓冲区的地址
    int len,                  要发送的字节数
    int flags                一般为0, MSG_DONTROUTE, MSG_OOB(外带数据)
);
成功返回发送字节数,出错返回SOCKET_ERROR
注意send函数把数据从buf复制到socket发送缓冲区后就返回了,
但是这些数据并不时马上就发送到连接的另一端。
在已连接的套接字上接受数据,recv函数是最基本的方式。
int recv(
    SOCKET s,
    char FAR* buf,
    int len,      准备接收的字节数或buf缓冲区长度

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。