和服务器用BLAB四部曲(bind()
、linsten()
、accept()
,开始对话
)不同,客户端只需要两步:
1、连接远程端口
2、开始通信
远程端口和IP地址
- 客户端需要知道远程服务器的IP地址和端口。
- IP地址很难记忆,一般使用域名。
- 网路中的数据包只使用数字的IP地址。
创建IP地址套接字
客户端套接字和服务器套接字以相同的方式创建。
#include <sys/socket.h>
...
int s = socket(PF_INET,SOCK_STREAM,0);
//s是套接字的描述符->互联网套接字
//0是协议号,默认填0就可以。
、、、
if(s == -1)
error("无法打开套接字");
但是客户端和服务器套处理套接字的方式不同。
struct sockaddr_in si;
si.sin_family = PF_INF;
si.sin_addr.s_addr = int_addr("208.201.239.100");
si.sin_port=htons(80);
connect(s,(struct sockaddr *)&si,sizeof(si));
getaddrinfo()获取域名地址
域名系统(Domain Name System,DNS)
创建域名套接字
为了使用DNS,余姚以另一种方式构建客户端套接字:
#include <netdb.h>
//使用getaddrinfo()函数需要的头文件
...
struct addrinfo *res;
struct addrinfo hints;
memset(&hints,0,sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo("www.oreilly.com","80",&hints,&res);
//getaddrinfo()接受字符串格式的端口号。
getaddrinfo()
会在堆上创建一种叫名字资源
的新数据结构。
给定域名和端口号,就可以得到名字资源。
名字资源把计算机需要的IP地址隐藏起来,大型网址通常有好几个IP地址,代码回从中挑选一个。
可以用名字资源创建套接字了:
int s = socket(res->ai_family,res->ai_socktype,ress->ai_protocol);
连接套接字,因为名字资源在堆上创建,因此要用freeaddrinfo()
的函数来清除它。
connect(s,res->ai_addr,res->ai_addrlen);
//res->ai_addr是远程主机
freeaddrinfo(res);
一旦连接到运城端口,就可以用recv()
和send()
函数读写数据了。
网友评论