目录
一、UDP模型
1、服务端
没有 accept,不需要建立建立连接;
使用 recvfrom 代替 read,失败返回 -1,成功返回 - 从内核缓冲区读到的字节数
使用 sendto 代替 write,失败返回 -1,成功返回 - 写到内核缓冲区的字节数
struct sockaddr_in servaddr;
struct sockaddr_in connaddr;
socklen_t servsocklen; // 本地已知
socklen_t connsocklen; // 对端未知
lfd = socket(AF_INET, SOCK_DGRAM, 0);
bind(lfd, &servaddr, servsocklen); //(struct sockaddr *)&servaddr
listen(lfd, maxlistensize);
while(1) {
// lfd 接收 data 从 connaddr, 传出 connaddr
len = recvfrom(lfd, buf, sizeof(buf), 0, &connaddr, &connsocklen); //(struct sockaddr *)&connaddr
// lfd 发送 data 到 connaddr, 传入 connaddr
len = sendto(lfd, buf, len, 0, &connaddr, connsocklen);
}
2、客户端
没有 connect,不需要建立建立连接;
使用 sendto 代替 write,失败返回 -1,成功返回 - 写到内核缓冲区的字节数
使用 recvfrom 代替 read,失败返回 -1,成功返回 - 从内核缓冲区读到的字节数
struct sockaddr_in servaddr;
struct sockaddr_in clieaddr;
socklen_t servsocklen; // 对端已知
socklen_t cliesocklen; // 本地已知
cfd = socket(AF_INET, SOCK_DGRAM, 0);
//bind(lfd, &clieaddr, cliesocklen); //(struct sockaddr *)&clieaddr
while(1) {
// cfd 发送 data 到 servaddr, 传入 servaddr
len = sendto(cfd, buf, len, 0, &servaddr, servsocklen); //(struct sockaddr *)&servaddr
// cfd 接收 data 从 servaddr, 传出 servaddr
len = recvfrom(cfd, buf, sizeof(buf), 0, &servaddr, &servsocklen);
// 显示
}
二、测试程序
1、服务端
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <string.h>
#define serv_ip "127.0.0.1"
#define serv_port 6666
int main()
{
char buf[BUFSIZ];
char clie_ipbuf[15];
int n = 0, i = 0;
int serv_fd;
struct sockaddr_in serv_addr; // 设置服务器地址
struct sockaddr_in clie_addr; // 待接受客户端地址
socklen_t clie_addr_len;
//
serv_fd = socket(AF_INET, SOCK_DGRAM, 0); // 创建socket, SOCK_DGRAM 报式协议 UDP
//
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);
//serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(serv_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); // serv_fd 绑定 serv_addr
//
listen(serv_fd, 128); // 设置最大同时连接数
while(1){
//读取
memset(buf, 0, sizeof(buf));
n = recvfrom(serv_fd, buf, sizeof(buf), 0, (struct sockaddr *)&clie_addr, (socklen_t *)&clie_addr_len);
if(n < 0){
perror("recvfrom error");
exit(1);
}
printf("client ip: %s, client port: %d\n", inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, clie_ipbuf, (socklen_t)sizeof(clie_ipbuf)), ntohs(clie_addr.sin_port));
printf("%s\n", buf);
//处理
for(i=0; i<n; i++)
{
buf[i] = toupper(buf[i]);
}
//回写
sendto(serv_fd, buf, n, 0, (struct sockaddr *)&clie_addr, (socklen_t)clie_addr_len);
}
close(serv_fd);
printf("server close...\n");
return 0;
}
2、客户端
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <string.h>
#define serv_ip "127.0.0.1"
#define serv_port 6666
#define clie_port 8888 // 固定端口
int main()
{
int n = 0;
char buf[BUFSIZ];
int clie_fd;
struct sockaddr_in clie_addr;
struct sockaddr_in serv_addr; //设置服务器地址
socklen_t clie_addr_len;
socklen_t serv_addr_len;
// socket
clie_fd = socket(AF_INET, SOCK_DGRAM, 0); //创建socket, SOCK_DGRAM : UDP
// clie_fd bind clie_addr
clie_addr.sin_family = AF_INET;
clie_addr.sin_port = htons(clie_port);
//inet_pton(AF_INET, clie_ip, &clie_addr.sin_addr.s_addr);
clie_addr.sin_addr.s_addr = htonl(INADDR_ANY); //
clie_addr_len = sizeof(clie_addr);
bind(clie_fd, (struct sockaddr *)&clie_addr, (socklen_t)clie_addr_len); // clie_fd 绑定 clie_addr
// serv_addr
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(serv_port);
//inet_pton(AF_INET, clie_ip, &clie_addr.sin_addr.s_addr);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); //
serv_addr_len = sizeof(serv_addr);
while(1)
{
//从屏幕读
memset(buf, 0, sizeof(buf));
fgets(buf, sizeof(buf), stdin); //fgts()读一行 hello ---> "hello\n\0"
buf[strlen(buf)-1] = 0; //将\n ---> \0
if(strcmp(buf, "quit") == 0) {break;}
n = sendto(clie_fd, buf, strlen(buf), 0, (struct sockaddr *)&serv_addr, serv_addr_len);
if(n < 0){
perror("sendto error");
exit(1);
}
//读取
memset(buf, 0, sizeof(buf));
n = recvfrom(clie_fd, buf, sizeof(buf), 0, (struct sockaddr *)&serv_addr, &serv_addr_len);
if(n < 0){
perror("recvfrom error");
exit(1);
}
//打印处理,有问题,可能不是C风格字符串
printf("%s\n", buf);
}
close(clie_fd);
printf("client close...\n");
return 0;
}