1 概述
udp的高并发服务器非常简单,因为不需要连接,所以我们服务器做好后,客户端只需要往服务器中发送数据即可,无论多少个客户端,都能发送数据,能不能处理就看服务器的处理能力。这样就实现了高并发。
2 代码
下面代码需要注意的是:
- 1)平时tcp调用socket函数的时候都是使用SOCK_STREAM作为参2,而udp实现的c/s使用SOCK_DGRAM。
- 2)并且服务器在recvfrom时必须获取传出的客户端地址,以便调用sendto函数的时候服务器可以指定发送信息给具体的客户端。而客户端的recvfrom无需获取,只需要传NULL即可,因为客户端sendto的时候已经指定服务器的地址,或者说服务器的地址是唯一的,已经提前确定了。
server.c
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <ctype.h>
#define SERV_PORT 8000
int main(void)
{
struct sockaddr_in serv_addr, clie_addr;
socklen_t clie_addr_len;
int sockfd;
char buf[BUFSIZ];
char str[INET_ADDRSTRLEN];
int i, n;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);/* 注意,平时tcp的时候都是使用SOCK_STREAM参数,而udp实现的c/s使用SOCK_DGRAM */
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(SERV_PORT);
bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
printf("Accepting connections ...\n");
while (1) {
clie_addr_len = sizeof(clie_addr);
n = recvfrom(sockfd, buf, BUFSIZ,0, (struct sockaddr *)&clie_addr, &clie_addr_len);//服务器必须获取客户端的传出地址,因为sendto要使用
if (n == -1)
perror("recvfrom error");
printf("received from %s at PORT %d\n",
inet_ntop(AF_INET, &clie_addr.sin_addr, str, sizeof(str)),
ntohs(clie_addr.sin_port));
for (i = 0; i < n; i++)
buf[i] = toupper(buf[i]);
n = sendto(sockfd, buf, n, 0, (struct sockaddr *)&clie_addr, sizeof(clie_addr));
if (n == -1)
perror("sendto error");
}
close(sockfd);
return 0;
}
client.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <ctype.h>
#define SERV_PORT 8000
int main(int argc, char *argv[])
{
struct sockaddr_in servaddr;
int sockfd, n;
char buf[BUFSIZ];
sockfd = socket(AF_INET, SOCK_DGRAM, 0);/* 注意,平时tcp的时候都是使用SOCK_STREAM参数,而udp实现的c/s使用SOCK_DGRAM */
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
servaddr.sin_port = htons(SERV_PORT);
while (fgets(buf, BUFSIZ, stdin) != NULL) {
n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
if (n == -1)
perror("sendto error");
n = recvfrom(sockfd, buf, BUFSIZ, 0, NULL, 0); //NULL:客户端不需要知道对端信息,但是服务器必须获取该传出参数,因为sendto需要客户端的地址
if (n == -1)
perror("recvfrom error");
write(STDOUT_FILENO, buf, n);/* 打印到屏幕 */
}
close(sockfd);
return 0;
}
结果如图,实现了高并发。