1.消息传递(管道、FIFO、消息队列)
2.同步(互斥量、条件变量、读写锁、文件和写记录锁、信号量)
3.共享内存(匿名的和具名的)
使用TCP/IP协议 通过socket完成
目的:实现不同系统上的源代码的可移植性。
举例:linux和windows都要实现基本的posix标准,linux把fork函数封装成posix_fork(随便说的),windows把creatprocess函数也封装成posix_fork,都声明在unistd.h里。这样,程序员编写普通应用时候,只用包含unistd.h,调用
int socket(int domain, int type, int protocol);
//参数分别是地址族、 套接字类型和协议
//AF_INET SOCK_STREAM 可默认为0
//IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd:即socket描述字
addr:一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址。
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 0.0.0.0 监听时,监听所有的地址
server_addr.sin_port = htons(port);
`
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 IP地址*/
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。但是我认为客户端也可以绑定。
小端:小字节放前面,大字节放后面
大端:大字节放前面,小字节放后面
转换端口
uint16_t htons(uint16_t hostshort); //主机字节序->网络字节序
uint16_t ntohs(uint16_t netshort); //网络字节序->主机字节序
转IP
htonl(uint32_t hostlong);//主机字节序->网络字节序
ntohl(uint32_t netlong);//网络字节序->主机字节序
int listen(fd,size) // 无错返回0,错误返回-1
服务端调用listen()后,开始监听网络上发送给socket的连接请求。
也就是说,开始接收请求了。
int connect(int sockfd,
const struct sockaddr *serv_addr,
int socklen_t addrlen);
accept()函数只做两件事,将连接请求从全连接队列中取出,给该连接分配一个fd并返回。
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
read()/write()
recv()/send()
readv()/writev()
recvmsg()/sendmsg()
recvfrom()/sendto()
#include
ssize_t read(int fd, void *buf, size_t count); // 目的fd 消息 消息长度
ssize_t write(int fd, const void *buf, size_t count);
#include
#include
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);
2个数据包同时被提出,但是由于数据是在一起的,没有办法分离
解决方法:
#include
int close(int fd);
close操作只是使相应socket描述字的引用计数-1,只有当引用计数为0的时候,才会触发TCP客户端向服务器发送终止连接请求。
1.正常情况下一方调用close情况如下图:
2.当双方同时调用close,如下图:
当同时发送close时,两边同时发送fin 和ack 这时候调用time_wait等待消息发送完毕。