第十四章、网络编程

14.1Windows Sockets的实现

Windows Sockets是Microsoft Windows的网络程序设计,以动态链接库的形式提供给我们使用。

14.1.1套接字的类型

流式套接字(SOCK_STREAM):流式套接字实际上是基于TCP协议实现的。数据报套接字(SOCK_DGRAM):数据包套接字实际上是基于UDP协议实现的。原始套接字(SOCK_RAW)

14.1.2基于TCP(面向连接)的Socket编程

基于TCP的Socket编程的服务器端程序流程:
1、创建套接字(socket)。
2、将套接字绑定到一个本地地址和端口上(bind)。
3、将套接字设置为监听模式,准备接收客户请求(Listen)。
4、等待客户请求;请求到来时,接收连接请求;返回一个新的此次连接的套接字(accept)。
5、用返回的套接字和客户端进行通信(send/recv)。
6、返回,等待另一客户的请求。
7、关闭套接字。

基于TCP的Socket编程的客户端程序流程:
1、创建套接字(socket)。
2、向服务器发送连接请求(connect)。
3、和服务器端进行通信(send/recv)。
4、关闭套接字。

客户端并不需要调用bind函数。因为服务器需要接收客户端的请求,所以必须要告诉本地主机服务器的IP和端口;但是当客户端发起连接,服务器接受后,服务器就保存了客户端的IP和端口。

14.1.3基于UDP(面向无连接)的Socket编程

我们把服务器端也叫接收端,客户端叫发送端。
服务器端的编写:
1、创建套接字(socket)。
2、将套接字绑定到一个本地地址和端口上(bind)。
3、等待接收数据(recvfrom)。
4、关闭套接字。
虽然面向无连接,但是数据接收需要相应的IP和端口,服务器端仍然需要bind函数。

客户端的编写;
1、创建套接字(socket)。
2、向服务器发送数据(sendto).
3、关闭套接字。
套接字相当于电话机,IP相当于总机号码,而端口号相当于分机号码

14.2相关函数

14.2.1WSAStartup函数

该函数有两个功能:一是加载套接字库,二是进行套接字库的版本协商。

int WSAStartup (
  WORD wVersionRequested,  
  LPWSADATA lpWSAData  
);

第一个参数指定要加载的Winsock库的版本,可以利用MAKEWORD(x,y)宏获得wVersionRequested的正确值。x是高位字节指定Winsock库的副版本,y是低字节则是主版本。
第二个参数指向WSADATA结构的指针,WSAStartup函数用其加载的库版本的有关信息填在这个结构中。
对于WSAStartup函数的成功调用(即成功加载Winsock动态库后),在最后都对应一个WSACleanUp调用,以便释放为该应用程序分配的资源,终止对Winsock动态库的使用。

14.2.2socket函数

加载了套接字库之后就可以调用socket函数创建套接字了:
SOCKET socket (int af,int type,int protocol);
第一个参数指定地址族,对于TCP/IP协议的套接字,它只能是AF_INET.
第二参数指定Socket类型,对于1.1版本,只支持流式套接字和数据报套接字。
第三个参数指定相关协议,若为0表示会自动选择一个合适的协议。
如果调用成功,就会返回一个新的SOCKET类型套接字描述符;调用失败,返回一个INVALID_SOCKET值,错误信息通过WSAGetLastError函数返回。

14.2.3bind函数

int bind (SOCKET s,const struct sockaddr FAR*  name,int namelen                        
);

第一个参数指定要绑定的套接字;第二个参数指定该套接字的本地地址信息,这是一个指向sockaddr结构的指针变量;第三个参数指定该地址结构的长度。

struct sockaddr {
        u_short    sa_family;
        char       sa_data[14];
};   

第一个字段指定地址家族,必须设置为AF_INET;第二个指定该区域中与协议相关的具体地址信息。

在基于TCP/IP的socket编辑过程中,可以用sockadd_in结构替换sockaddr,以方便我们填写地址信息。

struct sockaddr_in{
    short            sin_family;
    unsigned short      sin_port;
    struct   in_addr      sin_addr;
    char               sin_zero[8];
};

第二个参数指定要分配给套接字的端口;第三个参数指定要分配给套接字的IP地址;第四个参数是一个填充数,函数调用成功返回0

struct in_addr {
        union {
              struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
                struct { u_short s_w1,s_w2; } S_un_w;
                u_long S_addr;
        } S_un;

通常利用这个结构将一个点分十进制格式的IP地址转换为u_long类型,并将结果赋给成员S_addr。

14.2.4inet_addr和inet_ntoa函数

将地址指定为INADDR_ANY,将允许一个独立应用接受发自多个接口的回应。如果我们想让套接字使用多个IP地址中一个地址,就必须指定实际地址,用inet_addr函数来实现:
unsigned long inet_addr (const char FAR * cp);
该参数是一个字符串,指定了点分十进制格式表示的IP地址。返回一个适合分配给S_addr的u_long类型的数值。

inet_ntoa函数会完成相反的转换:
char FAR * inet_ntoa (struct in_addr in);
接受一个in_addr结构体类型的参数并返回一个点分十进制格式表示的IP地址字符串。

14.2.5listen函数

将套接字设置为监听模式。
int listen (SOCKET s,int backlog);
第一个参数是套接字描述符;第二个参数是等待连接队列的最大长度,如果将其设置为2,当三个请求同时到达时,前两个连接请求放到等待请求连接队列中,第三个连接请求就会被拒绝。

14.2.6accept函数

接受客户端发送的连接请求:
SOCKET accept (SOCKET s,struct sockaddr FAR* addr, int FAR* addrlen);
第一个参数是套接字描述符;第二个参数接收连接实体的地址;第三个参数返回包含地址信息的长度。

14.2.7send函数

通过已建立的套接字发送数据:
int send(SOCKET s,const char FAR * buf, int len,int flags);
第一个参数是一个已建立的套接字;第二个参数指要传递的数据;第三个参数传送数据的长度;第四个参数一般设置为0.

14.2.8recv函数

从一个已连接的套接字接收数据。
int recv (SOCKET s,char FAR* buf,int len,int flags);
参数与send函数一致。

14.2.9connect函数

将一个特定的套接字建立连接:
int connect(SOCKET s,const struct sockaddr FAR* name,int namelen);
第二个参数连接的服务器地址信息;第三个参数指定服务器端地址的长度。

14.2.10recvfrom函数

接收一个数据报信息并保存源地址
int recvfrom (SOCKET s,char FAR* buf,int len,int flags,struct sockaddr FAR* from,int FAR* fromlen);
第二个、第三个参数接收数据以及它的长度,第四个参数与send函数最后一个参数一致,第五个参数接收发送方的地址信息,最后一个参数返回地址结构的大小。

14.2.11sendto函数

向一个特定的目标方发送数据
int sendto (SOCKET s,const char FAR * buf,int len,int flags, const struct sockaddr FAR * to, int tolen);
第五个参数指定目标套接字的地址,最后一个参数指定地址的长度。

4.2.12htons和htonl函数

u_short htons (u_short hostshort );
将一个u_short类型的值从主机字节顺序转换为TCP/IP网络字节顺序。
与此类似的还有一个函数
u_long htonl (u_long hostlong);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

身影王座

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值