socket套接字,插销的意思,顾名思义,是要将两部分(c/s)套接在一起的意思。
socket的实质是linux中的一种文件类型,但是个伪文件(不占用存储空间)这就是为什么fgetc/fputc读写普通文件FILE*;使用recv/send读写socket的原因。
1、socket是成对存在的,C/S模型中,C(客户端)和S(服务器端)各有一个socket.
2、socket通过ip+端口号的形式将C和S进行连接。
3、socket是双向全双工的,即:C/S两端都都能同时收数据和发数据。
4、一个文件描述符fd有两个缓冲区(缓冲区是内核提供的4k大小左右的存储空间),一个用来读,一个用来写,所以是全双工的。
5、网络数据流采用的是大端字节序(低地址存高字节,高地址存低字节)(王大胆。。。)
主机字节序则是小端字节序(低地址低字节,高地址高字节)
例如;0x1234的存放
大端法 | 小端法 | |
地址 | 字节 | 字节 |
1001 | 34(低字节) | 12(高字节) |
1000 | 12(高字节) | 34(低字节) |
所以,c--->网络---->s 或者s-->网络-->C需要进行字节序的转换。
ip地址是4个字节,端口号是2个字节
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);//host to net 的ip地址转换
uint16_t htons(uint16_t hostlong);//host to net 的端口号转换
uint32_t ntohl(uint32_t netlong);//net to host 的ip地址转换
uint16_t ntohs(uint16_t netlong);//net to host 的端口号转换
除了以上四个函数外,经常用的2个函数:
#include <arpa/inet.h>
int inet_pton(int af,const char*src,void*dst);//点分十进制ip地址字符串直接转换成网络字节序
af:ip地址的类型,有两个值AF_INET----ipv4;AF_INET6----ipv6
src:"192.168.1.2"
dst:网络字节序的IP地址。
inet_ntop(int af,const void *src,char *dst,socklen_t size);
size:是dst数组的大小
6、地址类型的转换:
地址类型:struct sockaddr_in addr;//现在的地址类型
struct sockaddr;//之前的地址类型,已经废弃使用,但是函数参数时这个类型
我们每次使用都需要进行强制类型转换,
(struct sockaddr*)&addr;//强制类型转换
struct sockaddr_in{
sa_family_t sin_family;//地址族协议
in_port_t sin_port;//端口号
struct in_addr sin_addr;//ip地址
};
struct in_addr{
uint32_t s_addr;
};
7、服务器端建立socket顺序:
1)使用socket()函数创建socket
2)使用bind()函数将ip地址和端口号绑定到socket
3)使用listen()函数设置允许的最大连接数
4)使用accept()函数接收客户端过来的连接
5)使用read()函数和write()函数来收发数据。
6)关闭socket连接
8、客户端建立socket顺序:
1)使用socket()函数创建socket
2)使用connect()函数连接服务器端的ip和端口号
3)使用read()函数和write()函数来收发数据。
4)关闭socket连接