socket API

TCP网络通信:

1.IP地址(将消息发送到对方的机器上)+端口号(数据交给某个进程/应用程序进行解析)==标识某台主机的某个进程

2.一个进程可以绑定多个端口号(多线程),一个端口号不能被多个进程绑定

3.多字节数据相对内存地址有大端小端之分。

要求:发送主机发到缓冲区的数据按内存地址从低到高的发送(大端),接收主机接收数据至缓冲区时(大端),网络数据流低地址高字节(大端)

0x1234abcd --->0x0000

大端:0x12 0x34 0xab 0xcd

小端:0xcd 0xab 0x34 0x12

#include<arpa/inet.h>

uint32_t htonl(uint32_t hostlong)

uint16_t htons(uint16_t hostshort)

uint32_t ntohl(uint32_t  netlong)

uint16_t ntohs(uint16_t netshort)

4.int socket(int domain,int type,int protocol);//创建文件描述符  socket(AF_INET,SOCK_STREAM,0);

打开一个网络通讯端口,应用程序可以用read/write在网络上收发数据

struct sockaddr_in  (ipv4)   16位地址类型:AF_INET (sin_family)   16位端口号:TCP(SOCK_STREAM)  (sin_port)  32位IP地址(sin_addr)

struct sockaddr_in local;

local.sin_family=AF_INET;

local.sin_addr.s_addr=htonl(INADDR_ANY);

local.sin_port=htons(port);

struct sockaddr_un(ipv6)

sin_addr表示32位的IP地址,使用点分十进制的字符串表示IP地址,以下函数使用字符串表示和in_addri表示之间转换

字符串转in_addr函数

#include<arpa/inet.h>

int inet_aton(const char *strptr,struct in_addr *addrptr);

in_addr_t inet_addr(const char *strptr);

int inet_pton(int family,const char*strptr,void *addrptr);

in_addr转字符串函数

char *inet_ntoa(struct in_addr inaddr);返回一个Char*类型,这个结果放到了静态存储区,不需要手动释放资源

因为他把结果放到了一个静态存储区,多次调用会覆盖掉上一次的结果,inet_ntoa不是一个线程安全的函数,但是在实现多线程的测试中,结果没有出现问题,可能内部实现了互斥锁。多线程推荐使用inet_ntop,这个函数由调用者提供一个缓冲区保存结果。

bind函数:

int bind(int sockfd,const struct sockaddr*addr,socklen_t addrlen);

将sock和addr绑定在一起

(sock,(struct sockaddr*)&local,sizeof(local))

listen函数:

int listen(int sockfd,int backlog);//声明sock处于监听状态。最多允许几个客户端

accept函数:

int accept(int sockfd,struc sockaddr *addr,socklen_t *addrlen)

三次握手后,调用accept接受连接,如果调用accept时没有客户端连接请求,就阻塞等待直到有客户端连接上来。

addr是一个传出参数,accept返回时传出客户端地址和端口号

addr_len是传入传出参数,传入的是调用者提供的,传出的是客户端结构体实际长度

客户端使用connect连接服务器,bind参数是自己的地址,connect是对方的地址

int connect(int sockfd,const struct sockaddr*addr,socklen_t addrlen);

猜你喜欢

转载自blog.csdn.net/m0_43407388/article/details/108747620
今日推荐