socket基础详解 小白白

\#include <arpa/inet.h>

uint16_t htons(uint16_t hostshort);(将主机字节序转换为网络字节序162个字节) 

uint32_t htonl(uint32_t hostlong);(将主机字节序转换为网络字节序324个字节)

uint32_t ntohl(uint32_t netlong);  将网洛字节序转换为主机字节序 (324字节)

uint16_t ntohs(uint16_t netshort);  将网络字节序转换为主机字节序(162字节)

inet_pton() 将字符串类型的字节序转换为网络字节序

inet_ntop()网络字节序的地址转换位字符串类型的地址

其中inet_pton和inet_ntop不仅可以转换IPv4的in_addr,还可以转换IPv6的in6_addr。

int inet_pton(int af, const char *src, void *dst);const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

af 取值可选为 AF_INET 和 AF_INET6 ,即和 ipv4 和ipv6对应

支持IPv4和IPv6
在这里插入图片描述

    *sockaddr数据结构*

很多网络编程函数诞生早于IPv4协议,那时候都使用的是sockaddr结构体,为了向前兼容,现在sockaddr(以前的)退化成了(void *)的作用,传递一个地址给函数,至于这个函数是sockaddr_in(现在的需转换成以前的结构指针保证兼容)(可放更多的ip 占更多的空间)还是其他的,由地址族确定,然后函数内部再强制类型转化为所需的地址类型。


#include <sys/types.h> 

#include <sys/socket.h>

socket函数//创建信箱

int socket(int domain, int type, int protocol);

domain:

​	AF_INET 这是大多数用来产生socket的协议,使用TCP或UDP来传输,用IPv4的地址

    AF_INET6 与上面类似,不过是来用IPv6的地址

​	AF_UNIX 本地协议,使用在Unix和Linux系统上,一般都是当客户端和服务器在同一台及其上的时候  使用同一台主机没必要经过网络

type:

​	SOCK_STREAM 这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。

​	SOCK_DGRAM 这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。

​	SOCK_SEQPACKET该协议是双线路的、可靠的连接,发送固定长度的数据包进行传输。必须把这个包完整的接受才能进行读取。

​	SOCK_RAW socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使用该协议)

​	SOCK_RDM 这个类型是很少使用的,在大部分的操作系统上没有实现,它是提供给数据链路层使用,不保证数据包的顺序

protocol:

​	传0 表示使用默认协议。

返回值:

​	成功:返回指向新创建的socket的文件描述符,失败:返回-1,设置errno
*bind 函数*//绑定
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

sockfd:

​	socket文件描述符

addr:

​	构造出IP地址加端口号

addrlen:sizeof(addr)长度

返回值:

​	成功返回0,失败返回-1, 设置errno
struct sockaddr_in servaddr;

bzero(&servaddr, sizeof(servaddr));//使用之前必须清空

servaddr.sin_family = AF_INET;//协议

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//监听的地址

servaddr.sin_port = htons(6666);//端口
*listen 函数*//监听
int listen(int sockfd, int backlog);

sockfd:

​	socket文件描述符

backlog:

​	在Linux 系统中,它是指排队等待建立3次握手队列长度 如果这个队列满了再有客户端来进行三次握手是失败的,直到完成3次握手之后的客户端链接被清出队列,就空出了位置 ,就可以继续链接,并发越大就设置大一点,如果这个队列满了,多余的客户端链接就会被忽略掉

查看系统默认backlog

cat /proc/sys/net/ipv4/tcp_max_syn_backlog

`` 

改变 系统限制的backlog 大小

vim /etc/sysctl.conf

最后添加
net.core.somaxconn = 1024

net.ipv4.tcp_max_syn_backlog = 1024


保存,然后执行
sysctl -p

查看是否生效

sysctl -a | grep 1024

//相当于可以同时等待监听最多有多少个链接 返回int类型 listen()成功返回0,失败返回-1。 错误都会在errno中 这个队列存放还没有进行三次握手的链接 当完成三次握手之后 就执行accept(接受链接)就可以接收数据

//三次握手概念:(客户端commect 之后发送消息给服务端 这是第一次握手,服务端收到回一个信息给客户端,这是第二次握手,客户端收到再发信给服务端 这是第3次握手 完成之后就可以进行读写操作

在这里插入图片描述

****accept 函数****//接收客户端的链接//接收信箱 返回跟客户端得sock
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

sockdf:

​	socket文件描述符

addr:

​	传出参数,返回链接客户端地址信息,含IP地址和端口号

addrlen:

​	传入传出参数(值-结果),传入sizeof(addr)大小,函数返回时返回真正接收到地址结构体的大小

返回值:

​	成功返回一个新的socket文件描述符,用于和客户端通信,失败返回-1,设置errno

//服务器调用accept()接受连接,如果服务器调用accept()时还没有客户端的连接请求,就阻塞等待直到有客户端连接上来
****connect函数****客户端链接函数
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

sockdf:

​	socket文件描述符

addr:

​	传入参数,指定服务器端地址信息,含IP地址和端口号

addrlen:

​	传入参数,传入sizeof(addr)大小

返回值:

​	成功返回0,失败返回-1,设置errno

客户端需要调用connect()连接服务器,connect和bind的参数形式一致,区别在于bind的参数是自己的地址,而connect的参数是对方的地址。connect()成功返回0,出错返回-1。

*出错处理函数*

我们知道,系统函数调用不能保证每次都成功,必须进行出错处理,这样一方面可以保证程序逻辑正常,另一方面可以迅速得到故障信息。

出错处理函数

#include <errno.h>

#include <string.h>

char *strerror(int errnum);//此函数可写入到日志

errnum:

//比如

perror_exit(const char * des){

  //fprintf(stderr, "%s error, reason: %s\n", des, strerror(errno));//如果出错错误信息就会在全局的errno,stderr表示打印到标准出错des表示哪个地方出错就传字符串进去就可以打印出错误

  perror(des);//此函数只是打印到标志出错信息,不写入日志

  exit(1);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值