对于服务器,其通信流程一般有如下步骤:
调用socket函数创建socket,这一步会创建一个文件描述符FD。
调用bind函数将socket(也就是FD)绑定到某个ip和端口的二元组上。
调用listen函数开启侦听端口。
调用accept函数阻塞等待接受连接,当有客户端请求连接上来后,产生一个新的socket(客户端socket)。
基于新产生的socket调用send或recv函数开始与客户端进行数据通信。
通信结束后,调用close函数关闭客户端socket。
对于客户端,其通信流程一般有如下步骤:
调用socket函数创建客户端socket。
调用connect函数尝试连接服务器。
连接成功以后调用send或recv函数开始与服务器进行数据通信。
通信结束后,调用close函数关闭socket
原文链接:https://blog.csdn.net/u022812849/article/details/109670281
socket()函数 返回s_fd
#include <sys/types.h> /* 包含头文件 */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
1、domain TCP/IP协议 使用AF_INET(ip6使用AF_INET6)
2、type 常用SOCK_STREAM 用于TCP协议 ,SOCK_DGRAM 用于UDP
3、protocol 常用 0
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);//打开套接字
if (0 > socket_fd) {
perror("socket error");
exit(-1);
}
......
......
close(socket_fd); //关闭套接字
bind()函数:bind()函数用于将一个 IP 地址或端口号与一个套接字进行绑定(将套接字与地址进行关联)。
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
addr 是一个指针,一般使用 struct sockaddr_in 结构体,
struct sockaddr_in {
sa_family_t sin_family; /* 协议族 */
in_port_t sin_port; /* 端口号 */
struct in_addr sin_addr; /* IP 地址 */
unsigned char sin_zero[8];
};
例子:
struct sockaddr_in socket_addr;
memset(&socket_addr, 0x0, sizeof(socket_addr)); //清零
//填充变量
socket_addr.sin_family = AF_INET;
socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
socket_addr.sin_port = htons(5555);!!!!!!!!!
//或者填充
s_addr.sin_family =AF_INET;
s_addr.sin_port =htons(atoi(socketMes->port));
inet_aton(socketMes->ipAddress,&s_addr,sizeof(struct sockaddr_in));// !!!!!!
//将地址与套接字进行关联、绑定
bind(socket_fd, (struct sockaddr *)&socket_addr, sizeof(socket_addr));
Tips: 代码中的 htons 和 htonl 并不是函数,只是一个宏定义,主要的作用在于为了避免大小端的问题,需要这些宏需要在我们的应用程序代码中包含头文件<netinet/in.h>。
htonl()。 将主机数转换成无符号长整型的网络字节顺序。
htons是将整型变量从主机字节顺序转变成网络字节顺序, 就是整数在地址空间存储方式变为高位字节存放在内存的低地址处。
inet_aton是一个计算机函数,功能是将一个字符串IP地址转换为一个32位的网络序列IP地址。
atoi是把字符串转换成整型数的一个函数
Tips:bind()函数并不是总是需要调用的,只有用户进程想与一个具体的 IP 地址或端口号相关联的时候才需要调用这个函数。
listen()函数 让服务器进程进入监听状态,等待客户端的连接请求
int listen(int sockfd, int backlog);
accept()函数 使用 accept()函数获取客户端的连接请求并建立连接
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
发送和接收
read()函数
ssize_t read(int fd, void *buf, size_t count);
recv()函数
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
write()函数
ssize_t write(int fd, const void *buf, size_t count);
send()函数
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
tips: recv()和send()多出标志位