📄 linux_socket.txt
字号:
创建套接字:
int socket(int domain,int type,int protocol)
domain(地址族)取值:
AF_UNIX 1 UNIX域套接字(UNIX内部协议)
AF_INET 2 Internet协议
AF_X25 20 CCITT X.25 in particular
AF_IPX 23 Novell Internet Protocol
type(套接字类型)取值:
SOCK_STREAM 流套接字
SOCK_DGRAM 数据报套接字
SOCK_RAW 原始套接字
SOCK_SEQPACKET顺序数据包套接字
SOCK_RDM 可靠发送的消息套接字
protocol通常为0,表示IP
/etc/protocols:
ip 0 IP # internet protocol, pseudo protocol num
tcp 6 TCP # transmission control protocol
udp 17 UDP # user datagram protocol
ipv6 41 IPv6 # IPv6 in IP encapsulation
返回值:整数,套接字描述符(文件描述符)。
在互连网的进程通信中,全局标识一个进程需要一个(被称为"半相关"的)三元组
(协议,本地主机地址,本地端口号)
来描述,而一个完整的进程通信实例则需要一个(被称为"相关"的)五元组
(协议, 本地主机地址,本地端口号,远端主机地址,远端端口号)
来描述.
socket五元组中的第一个元素:协议。
绑定地址:
目的:绑定socket到端口等待接入
(1)服务器向系统注册它的(众所周知的)地址,(所有以这个地址接收的
数据包都交给该服务器);
(2)客户可为自己注册一个特定的地址;(若是面向连接,客户端可以不使用bind)
(3)无连接客户以此来保证系统给它分配唯一的地址,使服务器有合法的
返回地址给它发送应答信息。
( 注:当地址绑定到某个套接字以后,该套接字即不能再用来作任何其他通讯。)
bind函数说明:
int bind(int sd, struct sockaddr *addr, int addrlen)
sd: 套接字描述符
addr: 指向一协议专用的地址指针
struct in_addr{
ulong s_addr; /*32bit netid/hostid */
}
struct sockaddr_in{
short sin_family; /* socket类型 */
ushort sin_port; /*所用的端口 (>1024, 0-1023为公用端口)
struct in_addr sin_addr; /*所用的IP地址
char sin_zero[8]; /*未用*/
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;(相当于0.0.0.0,即如果系统有多条连接,
将接收任意Internet接口上的连接)
address.sin_port = htons(15000);
字节定序:(不同计算机系统中,存放数据的字节顺序不同,故
由网络协议指定网络字节顺序)
ulong htonl(ulong hostlong) 主机格式->网络格式(长整型)
ulong ntohl(ulong netlong) 网络格式->主机格式(长整型)
ushort htons(ulong hostshort) 主机格式->网络格式(短整型 )
ushort ntohs(ulong netshort) 网络格式->主机格式(短整型)
addrlen 地址标识结构的长度
bind(create_socket , (struct sockaddr *)&address,sizeof(address));
在套接字上建立连接:
(面向连接)建立虚电路;
(无连接)...
int connect(int sd,struct sockaddr_in *serveraddr,int addrlen)
sd 套接字描述符
serveraddr 目的套接字地址
1.两者必须具有相同的地址族和协议
2.对于UDP(无连接),connect只通知内核随后的send所使用的地址
(并不建立连接)
addrlen 地址标识结构的长度
通常:connect(create_socket,(struct sockaddr *)&address,sizeof(address)) ;
监听及接受连接请求(服务器)
若server响应一个client的请求,需要
1.表示愿意"听"将到来的连接请求(准备接受);(/*服务的关闭*/)
2.接受client的连接请求(对于TCP协议--面向连接)。
(1)监听
lisent(int sd,int backlog)
sd 套接字描述符
backlog 等待服务器接受的请求队列的最大长度(待处理请求的最大数目)。
(2)接受连接
int accept(int sd, struct sockaddr_in *peer, int *addrlen)
sd
peer 内核将所连接客户的地址填入peer(端)以返回给用户
addrlen 内核将所连客户地址所占空间重写到addrlen的内容中;
accept从队列中取出第一个连接请求--》
建立与之具有相同性能的另一套接字--》
父进程则循环在同一本地套接字上等待另一请求...
至此,新套接字所对应的五元组已全部填上
protocol local_a/p foreign_a/p
server socket bind listen accept
client socket connect
传送数据
(面向连接)
1. read/write
int read(int sd,char *buf,int nbytes)
int write(int sd,char *buf,int nbytes)
2. send/recv
int send(int sd,char *buf,int nbytes, int flag)
int recv(int sd,char *buf,int nbytes, int flag)
flag: 0或以下常数取"或"运算:
MSG_OOB 加急数据(即所发数据不属于正规数据交换部分,如远程模拟ctrl-c)
MSG_PEEK 观察到达的信息
...
以上四个均返回读写的数据长度;
(面向无连接)
int sendto(int sd,char *buf,int nbytes, int flag,
struct sockaddr_in *to,int addrlen)
to 数据发往的地址
int recv(int sd,char *buf,int nbytes, int flag,
struct sockaddr_in *from,int *addrlen)(地址长度返回给呼叫方)
from 由谁的地址读入
关闭套接字
close(int sd)
但对于可靠传输协议,系统应保证所有要发或应答的数据都已完成,故需让进程
放弃未传输的数据:
shutdown(int sd,int how)
how : 0 收方不想再读数据
1 发方没有数据要发送
2 双方均不允许发送数据
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -