您的位置:首页 > 新闻 > 热点要闻 > 网页设计作业10个页面_网络推广优化是干啥的_游戏推广代理平台_网页设计收费标准

网页设计作业10个页面_网络推广优化是干啥的_游戏推广代理平台_网页设计收费标准

2025/5/22 17:05:43 来源:https://blog.csdn.net/u014552102/article/details/145546624  浏览:    关键词:网页设计作业10个页面_网络推广优化是干啥的_游戏推广代理平台_网页设计收费标准
网页设计作业10个页面_网络推广优化是干啥的_游戏推广代理平台_网页设计收费标准

一、UDP服务器与客户端的区别

对于UDP服务器与客户端,两者都可以通过sendto和recvfrom函数收发数据,它们的主要区别是:

1.服务器一般是等待并响应来自客户端的请求,客户端则是主动发送请求并且等待服务器的响应。

2.服务器端要将地址和端口号绑定,如果不绑定就无法使用recvfrom函数接受数据(也就是说服务器需要调用bind函数将一个套接字与一个地址绑定,而客户端不需要)。所以对于UDP,其服务器与其说是服务端不如说是后发端。

所以如果阅读一份源码,要快速判断其是UDP服务器还是客户端,一个简单的方法是查看代码中是否调用了bind函数就可以了。

二、UDP是否可以使用select/poll/epoll

UDP是一种无连接的传输协议,因此通常情况下没有必要使用多路复用。UDP只是逐个接收数据段(数据包),并按照其规则进行处理,其并不关心单个数据包所属的任何特定数据流或数据包。但是UDP是可以使用select/poll/epoll的,某些开源软件,比如FFmpeg内部使用了这些多路复用来处理UDP。

三、使用poll函数编写UDP客户端、服务器程序

代码摘自:《IPV4 UDP server client program with Poll system call》

UDP客户端代码udpClient.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <signal.h>
#include <poll.h>#define BUFFER_SIZE 1024int client_socket = -1;static void sigint_handler(int signo)
{(void)close(client_socket);sleep(2);(void)printf("Caught sigINT!\n");exit(EXIT_SUCCESS);
}void validate_convert_port(
char *port_str,
struct sockaddr_in *sock_addr)
{int port;if (port_str == NULL) {perror("Invalid port_str\n");exit(EXIT_FAILURE);}if (sock_addr == NULL) {perror("Invalid sock_addr\n");exit(EXIT_FAILURE);}port = atoi(port_str);if (port == 0) {perror("Invalid port\n");exit(EXIT_FAILURE);}sock_addr->sin_port = htons((uint16_t)port);printf("Port: %d\n",ntohs(sock_addr->sin_port));
}void validate_convert_addr(
char *ip_str,
struct sockaddr_in *sock_addr)
{if (ip_str == NULL) {perror("Invalid ip_str\n");exit(EXIT_FAILURE);}if (sock_addr == NULL) {perror("Invalid sock_addr\n");exit(EXIT_FAILURE);}printf("IP Address: %s\n", ip_str);if (inet_pton(AF_INET, ip_str,&(sock_addr->sin_addr)) <= 0) {perror("Invalid address\n");exit(EXIT_FAILURE);}
}void recv_data(char *buffer)
{int ret, len;len = recvfrom(client_socket,buffer, BUFFER_SIZE, 0, NULL, NULL);if (len > 0) {buffer[len] = '\0';(void)printf("Received: %s\n",buffer);} else if (len == 0) {printf("Connection closed\n");exit(EXIT_FAILURE);}
}void register_signal_handler(
int signum,
void (*handler)(int))
{if (signal(signum, handler) == SIG_ERR){printf("Cannot handle signal\n");exit(EXIT_FAILURE);}
}int main(int argc, char *argv[])
{int ret, len;struct sockaddr_inserver_addr;char buffer[BUFFER_SIZE];struct pollfd fds[1];char *str = "HI";register_signal_handler(SIGINT,sigint_handler);if (argc != 3) {printf("%s<port-number><ip-addr>\n",argv[0]);exit(EXIT_FAILURE);}memset(&server_addr, 0,sizeof(server_addr));server_addr.sin_family = AF_INET;validate_convert_port(argv[1],&server_addr);validate_convert_addr(argv[2],&server_addr);client_socket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);if (client_socket < 0) {perror("socket");return -1;}while (1) {ret = sendto(client_socket, str,strlen(str), 0,(struct sockaddr*)&server_addr,sizeof(server_addr));printf("sendbuffer = %s\n", str);if (ret < 0) {perror("send error\n");(void)close(client_socket);break;}fds[0].fd = client_socket;  fds[0].events = POLLIN;ret = poll(fds, 2, 1000);if (ret < 0) {perror("poll");(void)close(client_socket);break;}if (fds[0].revents & POLLIN) {recv_data(buffer);}}(void)close(client_socket);return 0;
}

UDP服务器代码udpServer.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <signal.h>
#include <poll.h>#define BUFFER_SIZE 1024int server_socket = -1;static void sigint_handler(int signo)
{(void)close(server_socket);sleep(2);(void)printf("Caught sigINT!\n");exit(EXIT_SUCCESS);
}void register_signal_handler(
int signum,
void (*handler)(int))
{if (signal(signum, handler) == SIG_ERR) {printf("Cannot handle signal\n");exit(EXIT_FAILURE);}
}void validate_convert_port(
char *port_str,
struct sockaddr_in *sock_addr)
{int port;if (port_str == NULL) {perror("Invalid port_str\n");exit(EXIT_FAILURE);}if (sock_addr == NULL) {perror("Invalid sock_addr\n");exit(EXIT_FAILURE);}port = atoi(port_str);if (port == 0) {perror("Invalid port\n");exit(EXIT_FAILURE);}sock_addr->sin_port = htons((uint16_t)port);printf("Port: %d\n",ntohs(sock_addr->sin_port));
}void recv_send(
char *buffer,
struct sockaddr_in *client_addr)
{int len, ret;socklen_t client_addr_len = sizeof(client_addr);len = recvfrom(server_socket,buffer, BUFFER_SIZE, 0,(struct sockaddr*)&client_addr,&client_addr_len);if (len > 0) {buffer[len] = '\0';printf("Received: %s\n",buffer);memset(buffer, 0,sizeof(buffer));strncpy(buffer, "HELLO",strlen("HELLO") + 1);buffer[strlen(buffer) + 1] = '\0';ret = sendto(server_socket,buffer,strlen(buffer), 0,(struct sockaddr*)&client_addr,client_addr_len);if (ret < 0) {perror("sendto");exit(EXIT_FAILURE);}} else if (len < 0) {perror("recvfrom");exit(EXIT_FAILURE);}printf("Sentbuffer = %s\n",buffer);
}int main(int argc, char *argv[])
{int ret;struct sockaddr_inserver_addr,client_addr;char buffer[BUFFER_SIZE];struct pollfd fds[1];register_signal_handler(SIGINT,sigint_handler);if (argc != 2) {printf("%s <port-number>",argv[0]);exit(EXIT_FAILURE);}memset(&server_addr, 0,sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr =INADDR_ANY;validate_convert_port(argv[1],&server_addr);server_socket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);if (server_socket < 0) {perror("socket");return -1;}ret = bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr));if (ret < 0) {perror("bind");(void)close(server_socket);return -2;}printf("UDP listining\n");memset(fds, 0, sizeof(fds));fds[0].fd = server_socket;fds[0].events = POLLIN;while (1) {ret = poll(fds, 1, 1000);if (ret < 0) {perror("poll");break; }if (fds[0].revents & POLLIN) {recv_send(buffer, &client_addr);}}(void)close(server_socket);return 0;
}

编译:

gcc udpClient.c -o udpClient -g
gcc udpServer.c -o udpServer -g

运行:

客户端执行命令:

./udpClient 1234 127.0.0.1

服务器执行命令:

./udpServer 1234

运行后两者即可通讯。

从上面的代码可以看出来,上述UDP客户端和服务器都使用了poll函数监视文件描述符是否可读。区别在于服务器调用了bind函数将套接字与地址绑定,而客户端没有调用bind函数而已。

四、参考

《UDP服务器与客户端之间的区别?》

《UDP协议为什么分客户端和服务器端》

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com