本篇是对《深入理解计算机系统(原书第三版3)》第十一章网络编程关于套接字的内容的复习笔记。
基本概念
一个套接字是连接的一个端点
;
每个套接字都有相应的套接字地址:因特网地址 + 一个16位的整数端口组成(格式为地址:端口);
客户端套接字地址中端口通常由内核自动分配,称为临时端口;服务器套接字地址中的端口通常为知名端口;
/etc/services 包含一张本机器提供的知名名字和知名端口之间的映射;
一个连接由套接字对
唯一确定;
套接字接口是一组函数,它们和Unix函数结合起来,用以创造网络应用;
AF_INET:IPv4 网络协议的套接字类型;
为什么会出现sockaddr_in和sockaddr?书中给了一个解释是方便定义connect、bind、accept这些函数,使它们能接受各种类型的套接字地址结构;
socket连接机制
- socket函数:
客户端和服务器使用socket函数来创建一个套接字描述符
:
|
|
SOCK_STREAM表示这个套接字是连接的一个端点;
- connect函数:
客户端通过调用connect函数来建立和服务器的连接
:
|
|
其中sockaddr是服务器的套接字地址,addrlen是sizeof(sockaddr_in);
如果连接成功,clientfd描述符就“打开”,准备好可以读写了;
- bind函数:
|
|
将addr中的服务器套接字地址和套接字描述符sockfd联系起来;
- listen函数:
|
|
listen将sockfd从一个主动套接字转化为一个监听套接字,然后接受来自客户端的连接请求;
backlog参数暗示了内核在开始拒绝连接请求之前,队列中要排队完成的连接请求数量,通常设置为一个较大值,比如1024;
- accept函数:
|
|
accept函数等待来自客户端的连接请求到达监听描述符listenfd,然后在addr中填写客户端的套接字地址,并返回一个已连接描述符;
- getaddrinfo函数:
将主机名、主机地址、服务名和端口号的字符串转化成套接字地址结构;
- getnameinfo函数:
getnameinfo函数和getaddrinfo是相反的,将一个套接字地址结构转换成相应的主机和服务名字符串;
getaddrinfo和getnameinfo可以用来为一些函数自动生成并提供参数;
套接字的连接机制可以大致用一张图来表示:
Java编写socket
接下来用Java编写一个简单的socket程序。
首先是客户端:
|
|
在这段代码中并没有connect(),当然,即便有,它也并不是前文中那个connect(),从这点就能看出Java对底层代码进行了封装,如果要模拟底层的构造但不连接形式,可以将Socket client = new Socket(host, port);
替换成:
|
|
接下来再写一个简单的服务器端:
|
|
ServerSocket将底层的函数封装起来,提供简便的api,运行服务器端,然后执行客户端,服务器端打印出”你好”;
小结
本篇算是对套接字进行了一个简单的复习,了解了套接字的连接机制。
参考
问题
客户端需要将套接字描述符和客户端套接字地址联系起来吗??
listenfd是怎么产生的?