UDP-C/S 通信
udp服务器,默认支持多个 客户端并行访问。因为,不需要连接。直接使用 IP+port 对应传输数据。
TCP和UDP对
| tco | udp |
---|
特征 | 面向连接的可靠的数据包传输 | 无连接的不可靠的报文传递。 | 优点 | 速度、顺序、数据量可靠。利用回执,丢包重传保证数据包到达,传输稳定。 | 速度快,开销小。 | 缺点 | 速度慢、开销大。 | 不可靠。速度、顺序、数据流量。没有丢包重传机制。 | 应用场景 | 对数据稳定性要求较高场合。如:大文件传输。 | 对数据传输效率要求较高场合。简单网络环境(局域网) |
C/S 通信
相关函数
recvfrom。 ( accept + read )
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
sockfd: socket()返回值,用于数据通信的套接字。
buf:存数据的缓冲区
len:缓冲区大小。
flags:0
src_addr:传出。 对端的地址结构(IP+port)。
addrlen:传入传出。src_addr 大小。
返回值:实际读到字节数。
sendto。( connect + write )
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
sockfd: socket()返回值,用于数据通信的套接字。
buf:存数据的缓冲区
len:缓冲区中实际数据的大小。
flags:0
src_addr:传入。 目标端的地址结构(IP+port)。
addrlen:src_addr大小。
返回值:实际写出的字节数。
bind()
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
功能:
将本地协议地址与 sockfd 绑定,这样 ip、port 就固定了
参数:
sockfd:socket 套接字
addr: 指向特定协议的地址结构指针
addrlen:该地址结构的长度
返回值:
成功:返回 0
失败:-1
cfd = socket(AF_INET,SOCK_DGRAM, 0) 绑定地址结构bind() Accept() recvfrom() 读。 /注意 recv()和send() 只能用于tcp/ 数据处理 sendto()写。
UDP 服务代码参考
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define SERV_PORT 10086
int main(void)
{
int cfd;
cfd = socket(AF_INET, SOCK_DGRAM, 0);
char buf[1024], clie_IP[BUFSIZ];
int ret, i;
struct sockaddr_in serv_addr, clie_addr;
socklen_t clie_addr_len;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(cfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
clie_addr_len = sizeof(clie_addr);
while (1) {
ret = recvfrom(cfd, buf, sizeof(buf), 0, (struct sockaddr *)&clie_addr, &clie_addr_len);
printf("client 's IP:%s port:%d\n",
inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, clie_IP, sizeof(clie_IP)),
ntohs(clie_addr.sin_port));
for (i = 0; i < ret; i++)
buf[i] = toupper(buf[i]);
sendto(cfd, buf, ret, 0, (struct sockaddr *)&clie_addr, clie_addr_len);
}
close(cfd);
return 0;
}
UDP客户端代码参考
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define SERV_PORT 10086
#define SERV_IP "127.0.0.1"
int main(void)
{
int cfd;
cfd = socket(AF_INET, SOCK_DGRAM, 0);
char buf[BUFSIZ];
int ret;
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, SERV_IP, &serv_addr.sin_addr.s_addr);
while (1) {
fgets(buf, sizeof(buf), stdin);
sendto(cfd, buf, strlen(buf), 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
ret = recvfrom(cfd, buf, sizeof(buf), 0, NULL, NULL);
write(STDOUT_FILENO, buf, ret);
}
close(cfd);
return 0;
}
UDP客户端注意事项:
1)本地IP、本地端口(我是谁)
2)目的IP、目的端口(发给谁)
3)在客户端的代码中,我们只设置了目的IP、目的端口
4)客户端的本地 ip、本地 port 是我们调用 sendto 的时候 linux 系统底层自动给客户端分配的;分配端口的方式为随机分配,即每次运行系统给的 port 不一样。
更多参考https://blog.csdn.net/dengjin20104042056/article/details/103018920
|