Linux Socket 编程学习

一、Socket起源
网络中进程之间如何通信、如何标识进程?
网络层的ip地址:用来标识网络中的主机
传输层的协议+端口:用来标识主机中的应用程序(进程)
总结:利用ip地址、协议、端口可以标识网络中的进程。

二、socket函数
1.socket函数
原型:int socket(int domain, int type, int protocol)
功能:socket()用于创建一个socket描述符,唯一标识一个socket,对应于普通文件的打开操作
参数:
domain:协议域,又称为协议族。常用的协议族有:AF_INET、AF_INET6
type:指定socket类型。常用的socket类型有:SOCK_STREAM、SOCK_DGRAM
protocol:指定协议。常用的协议有:IPPROTO_TCP( TCP传输协议)、IPPTOTO_UDP( UDP传输协议)
返回值:socket描述符
2.bind函数
原型:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
功能:把sockaddr 信息和 sockfd 绑定在一起
参数:
sockfd:socket描述字
addr:const struct sockaddr *指针,指向要绑定给sockfd的协议地址
addrlen:对应的是地址的长度 sizeof(struct sockaddr)
返回值:
0:表示成功
-1:表示失败

struct sockaddr_in {
    sa_family_t    sin_family; /* address family: AF_INET */
    in_port_t      sin_port;   /* port in network byte order */
    struct in_addr sin_addr;   /* internet address */
};
struct in_addr {
    uint32_t       s_addr;     /* address in network byte order */
};

注:服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。
3.listen函数
原型:int listen(int sockfd, int backlog)
功能:作为一个服务器,在调用socket()、bind()之后就会调用listen()来监听这个socket
参数:
sockfd:服务器的socket描述字
backlog:socket可以排队的最大连接个数
返回值:
0:表示成功
-1:表示失败
注:socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。
4.connect函数
原型:int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
功能:发出连接服务端请求
参数:
sockfd: 客户端的socket描述字
addr:服务器的socket地址和端口信息
addrlen:socket地址的长度
返回值:
0:表示成功
-1:表示失败
5.accept函数
原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
功能:accept()函数去阻塞接收客户端请求
参数:
sockfd:服务器的socket描述字
addr:用于返回客户端的协议地址
addrlen:协议地址的长度
返回值:
如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与返回客户的TCP连接,后面通过该描述字进行通信。
6.close函数
原型:int close(int fd)
功能:关闭socket描述字
参数:
fd:socket描述字
返回值:
0:表示成功
-1:表示失败
7.读写函数

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);

#include <sys/types.h>
#include <sys/socket.h>

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
               const struct sockaddr *dest_addr, socklen_t addrlen);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                 struct sockaddr *src_addr, socklen_t *addrlen);

ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

8、setsockopt函数
原型:int setsockopt(int sockfd, int level, int option, const void *val, socklen_t len);
头文件:#include <sys/socket.h>
参数:
sockfd:我们要进行配置的socket
level:根据我们选用的协议,配置相应的协议编号
option:选项即为上表
最后参数是用来存放返回值
在这里插入图片描述
9、shutdown函数
原型:int shutdown(int sockfd,int howto);
参数:
sockfd:sockfd描述符
howto:
SHUT_RD:值为0,关闭连接的读这一半。
SHUT_WR:值为1,关闭连接的写这一半。
SHUT_RDWR:值为2,连接的读和写都关闭。

注:
close 和 shutdown区别:
close 一个套接字的默认行为是把套接字标记为已关闭,然后立即返回到调用进程,该套接字描述符不能再由调用进程使用,也就是说它不能再作为read或write的第一个参数,然而TCP将尝试发送已排队等待发送到对端的任何数据,发送完毕后发生的是正常的TCP连接终止序列。
在多进程并发服务器中,父子进程共享着套接字,套接字描述符引用计数记录着共享着的进程个数,当父进程或某一子进程close掉套接字时,描述符引用计数会相应的减一,当引用计数仍大于零时,这个close调用就不会引发TCP的四路握手断连过程。

终止网络连接的通用方法是调用close函数。但使用shutdown能更好的控制断连过程

close函数会关闭套接字ID,如果有其他的进程共享着这个套接字,那么它仍然是打开的,这个连接仍然可以用来读和写,并且有时候这是非常重要的 ,特别是对于多进程并发服务器来说。
而shutdown会切断进程共享的套接字的所有连接,不管这个套接字的引用计数是否为零,那些试图读得进程将会接收到EOF标识,那些试图写的进程将会检测到SIGPIPE信号,同时可利用shutdown的第二个参数选择断连的方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值