网络编程--TCP/UDP 通信模型

网络编程模型


在这里插入图片描述

上述模型中,每个概念的含义如下:

  1. Socket: 建立 Socket。创建一个 Socket 描述符;
  2. bind: 用于服务器端,把 Socket 的描述符与协议类型、本地IP、本地端口等信息进行绑定;
  3. listen: 用于服务器端,主要用于监听来自外部的连接,可以设置最大允许外部连接的数量;
  4. connect: 用于客户端,向服务器发起连接;
  5. accept: 用于服务器,接收客户端的连接请求。此时会返回一个与该客户端对应的新的 Socket 描述符,与该客户端的通信使用此 Socket 的描述符;
  6. send/sendto: 通过 Socket 的发送数据;
  7. recv/recvfrom: 通过 Socket 的接收数据;
  8. 关闭 Socket 的。

主要函数详解


建立套接字 socket()


在这里插入图片描述

常用实例为:

/*创建IPv4 TCP Socket*/
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == sfd) {
    perror("socket");
    exit(-1);
}

绑定地址 bind()


bind() 绑定函数的作用:主要用于把 socket 绑定到主机地址上。

在这里插入图片描述

常用实例:

// 初始化主机信息
struct sockaddr_in my_addr;
memset(&my_addr, 0, sizeof(struct sockaddr_in)); // 清空主机地址
// bzero(&my_addr, sizeof(struct sockaddr_in));
my_addr.sin_family = AF_INET; // 定义协议族:IPV4
my_addr.sin_port = htons(8888); // 定义端口号:把主机字节序转化为网络字节序
my_addr.sin_addr.s_addr = inet_addr("192.168.0.101") ; // 将ip 点分十进制转化为二进制,并转化为网络字节序
// 把 socket 绑定到主机地址上 
if(bind(sfd, (struct sockaddr *)&my_addr), sizeof(struct sockaddr_in) == -1) {
    perror("bind");
    close(sfd);
    exit(-1);
}

注意:

  • 如果设置:my_addr.sin_port = 0,函数会自动选择一个未占用的端口来使用;
  • 如果设置: my_addr.sin_addr.s_addr = INADDR_ANY,系统会自动填入本机 IP 地址;

监听 listen()


listen 函数:主要作用是用于监听端口,检测是否有连接请求信号。

在这里插入图片描述

常用实例:

// 监听 sfd,设置最大的连接数为 10
if(listen(sfd, 10) == -1) {
    perror("listen");
    close(sfd);
    exit(-1);
}

接受请求 accept()


accept 函数用于接受远程客户端的连接请求,建立与客户机之间的通信连接。假如没有客户端发出请求,服务器默认将在此处阻塞。

在这里插入图片描述

注意: 服务器处于监听状态时,如果某时刻获得了客户机的连接请求,此时并不是立即处理这个请求,而是将这个请求放在等待队列中,当系统有空闲时再处理客户机的连接请求。

常用实例:

struct sockaddr_in clientaddr; // 用于存储客户端主机信息
bzero(&clientaddr, sizeof(struct sockaddr)); // 情况结构 clientaddr
int addrlen = sizeof(struct sockaddr_in); // 计算结构 clientaddr 的长度
// 接收客户端的请求,并把客户端 socket 数据存入结构 clientaddr 中。
int new_fd = accept(sfd, (struct sockaddr *)&clientaddr, &addrlen); // 返回客户端 Socket
if (-1 == new_fd) {
    perror("accept");
    close(sfd);
    exit(-1);
}
print("%s %d success connect\n", inet_ntoa(clientaddr.sin_addr), ntoths(clientaddr.sin_port));

连接服务器 connect()


connect 函数:将客户端 Socket 连接至服务器。主要用在 TCP 客户端。

在这里插入图片描述

常用实例:

// 存储服务器IP、端口信息
struct sockaddr_in saddr; // 用于存储服务器socket数据
bzero(&seraddr, sizeof(struct sockaddr_in)); // 清空结构 saddr
seraddr.sin_family = AF_INET; // IPv4 网络
seraddr.sin_port = htons(8888); // 把端口设置为网络字节序
seraddr.sin_addr.s_addr = inet_addr("192.168.0.101"); // 把服务器IP设置为网络字节序的二进制

// 本地socket连接服务器的socket.
if(connect(cfd, (struct sockaddr *)&saddr, sizeof(struct sockaddr)) == -1) {
    perror("connect");
    close("sfd");
    exit(-1);
} 

发送数据 send()/sendto()


send 函数:主要用在 TCP 协议中,其作用是向指定的服务器/客户端发送数据;
sendto() 函数:主要用在 UDP 协议中,其作用是向指定的服务器/客户端发送数据;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

常用实例:

// 在 TCP 中,服务器(客户端)向客户端(服务器)发送字符串 "hello"。
if(send(client_fd, "hello", 6, 0) == -1) {
    perror("send");
    close(client_fd);
    exit(-1);
}

// 在 UDP 中,服务器(或客户端)向客户端(或服务器)发送字符串 "hello",
// 在UDP中,需要指明对方的地址信息(socket信息)
if(sendto(socket_fd, "hello", 6, 0, (struct sockaddr *)&toaddr, sizeof(struct sockaddr) == -1) {
    perror("sendto");
    close(client_fd);
    exit(-1);
} 

接收数据 recv()/recvfrom()


recv() 函数:主要用在 TCP 中,其作用是接收来自服务器/客户端的数据;
recvfrom() 函数:主要用在 UDP 中,其作用是接收来自服务器/客户端的数据;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

常用实例:

// 在 TCP 中,recv 通过已经建立联系的socket client_fd 进行联系
// 服务器(客户端)向客户端(服务器)发送数据
char buf[512] = {0};
if(recv(client_fd, buf, sizeof(buf), 0) == -1) {
    perror("recv");
    close(client_fd);
    exit(-1);
}
puts(buf);

// 在 UCP 中,服务器(客户端)向客户端(或服务器)发送数据;
// 需要指明对方的socket信息
char buf[512] = {0};
if(recvfrom(socket_fd, buf, sizeof(buf), 0, (struct sockaddr *)&fromaddr, sizeof(struct sockaddr)) == -1) {
    perror("recvfrom");
    close(socket_fd);
    exit(-1);
}
puts(buf);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值