一、概念
1.1 套接字
套接字成对出现
一个socket=一个文件描述符+两份缓冲区
二、socket
2.1 网络字节序
大端法:低存高 ,高存低,网络存储 0x78563412
小端法:低存低 ,高存高,pc存储 0x12345678
转换函数
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
//host to network long,本地转网络 32位,针对于ip
//转本地
uint16_t htons(uint16_t hostshort);
//16位,针对port
uint32_t ntohl(uint32_t netlong);
// network long to host,网络转本地 32位,针对于ip
uint16_t ntohs(uint16_t netshort);
//16位,针对port
----------------------------------------------------------------------
int inet_pton(int af, const char * src, void * dst);
/*ip to network ip地址直接转为网络
af:AF_INET, AF_INET6 ipv4与ipv6
src: ip地址(点分十进制)
dst: 转换后的结果
*/
const char *inet_ntop(int af, const void * src, char * dst, socklen_t size);
//size:dst的大小
2.2 sockaddr
由于现在把sockaddr定义改成了sockaddr_in,但其他函数使用没改,所以要强转,传参时处理方法
//sockaddr_in的定义
struct sockaddr_in{
sa_family_t sin_family;//地址类型,AF_INET和AF_INET6 即为ipv4和ipv6
in_port_t sin_port;//网络字节序 port
struct in_addr sin_addr;//网络地址
};
struct in_addr{
uint32_t s_addr//网络ip地址
};
//初始化方法
addr.sin_family=AF_INET/AF_INET6
addr.sin_port=htons(1234);
//sin_addr赋值方法1
int dst;
inet_pton(AF_INET,"111.111.111",(void*)&dst);
addr.sin_addr.s_addr =dst;
//sin_addr赋值方法2
「*」addr.sin_addr.s_addr = htonl(INADDR_ANY);//此函数可以获取系统有效的的ip,且为二进制
//转换方法
struct sockaddr_in addr;
bind((struct sockaddr*)&addr);
2.3 相关函数介绍
image.pngsocket:创建socket
bind:绑定IP+PORT
listen:设置监听上限,同时建立socket的数量
accept:阻塞监听客户端连接,成功返回一个与客服端socket连接的socket文件描述符
#include<sys/socket.h>
int socket(int domain, int type, int protocol);
/*
domain: AF_INET, AF_INET6, AF_UNIX
type: SOCK_STREAM,SOCK_DGRAM
protocal: 0
返回值:成功文件描述符,失败errno
*/
int bind(int socket, const struct sockaddr *address, socklen_t address_len);
//socklen_t len=sizeof(addr);
int listen(int socket, int backlog);
//backlog 上限数值
int accept(int socket, struct sockaddr * address,socklen_t *address_len);
/*
socket:函数返回值
address:传出参数,客户端的地址结构
addrlen:传入传出参数,传入addr大小,传出客户端addr大小
*/
int connect(int socket, const struct sockaddr *address, socklen_t address_len);
//使用现有socket与服务器连接
/*
address:要连接的服务器的地址结构
*/
三、高并发服务器
3.1 多进程并发服务器
通过父子进程来实现,父进程监听,子进程处理连接及通信
socket();
bind();
listen();
while(1){
cfd=accept();
pid=fork();
if(pid==0){
close(lsd);
read();write();
}else if(pid>0){
close(cfd);
continue;
}
}
注意回收进程以免僵尸
3.2 多线程并发服务器
socket();
bind();
listen();
while(1){
cfd=accept();
pthread_create();
pthread_detach();
}
//子线程
void* tfn(){
close();
read();write();
}
使用detach让线程自动回收
网友评论