UDP (User Datagram Protocol):用户数据报协议。

UDP 是一个不可靠的通信协议,没有重传和确认,没有有序控制,也没有拥塞控制。可以简单地理解为,在 IP 报文的基础上,UDP 增加的能力有限。

UDP编程

UDP中客户端和服务器端交互的图解:

UDP Server :

Create UDP socket.Bind the socket to server address.Wait until datagram packet arrives from client.Process the datagram packet and send a reply to client.Go back to Step 3.

UDP Client :

Create UDP socket.Send message to server.Wait until response from server is received.Process reply and go back to step 2, if necessary.Close socket descriptor and exit.

主要是使用以下函数:

#include

ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags,

struct sockaddr *from, socklen_t *addrlen);

ssize_t sendto(int sockfd, const void *buff, size_t nbytes, int flags,

const struct sockaddr *to, socklen_t *addrlen);

recvfrom的参数含义:

sockfd :本地创建的套接字描述符

buff :指向本地缓存的指针

nbytes :最大接收数据字节

flags :与 I/O 相关的参数

from 和 addrlen:返回对端发送方的地址和端口等信息

返回值:实际接收的字节数。

sendto的参数意义:

sockfd :本地创建的套接字描述符

buff :指向本地缓存的指针

nbytes :最大接收数据字节

flags :与 I/O 相关的参数

to 和 addrlen,表示发送的对端地址和端口等信息。

UDP例子

UDP Server:

// Server side implementation of UDP client-server model

#include

#include

#include

#include

#include

#include

#include

#include

#define PORT 8080

#define MAXLINE 1024

// Driver code

int main() {

int sockfd;

char buffer[MAXLINE];

char sendbuffer[MAXLINE];

struct sockaddr_in servaddr, cliaddr;

// Creating socket file descriptor

if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {

perror("socket creation failed");

exit(EXIT_FAILURE);

}

memset(&servaddr, 0, sizeof(servaddr));

memset(&cliaddr, 0, sizeof(cliaddr));

// Filling server information

servaddr.sin_family = AF_INET; // IPv4

servaddr.sin_addr.s_addr = INADDR_ANY;

servaddr.sin_port = htons(PORT);

// Bind the socket with the server address

if ( bind(sockfd, (const struct sockaddr *)&servaddr,

sizeof(servaddr)) < 0 )

{

perror("bind failed");

exit(EXIT_FAILURE);

}

int n;

socklen_t len = (socklen_t)sizeof(cliaddr); //len is value/resuslt

for (;;) {

n = recvfrom(sockfd, (char *)buffer, MAXLINE,

MSG_WAITALL, ( struct sockaddr *) &cliaddr,

&len);

buffer[n] = '\0';

printf("Client : %s\n", buffer);

sprintf(sendbuffer, "have recieve %d bytes", strlen(buffer));

sendto(sockfd, (const char *)sendbuffer, strlen(sendbuffer), 0,

(const struct sockaddr *) &cliaddr, len);

fprintf(stdout, "%s\n", sendbuffer);

}

return 0;

}

UDP Client:

// Client side implementation of UDP client-server model

#include

#include

#include

#include

#include

#include

#include

#include

#define PORT 8080

#define MAXLINE 1024

// Driver code

int main() {

int sockfd;

char buffer[MAXLINE];

char *hello = "Hello from client";

struct sockaddr_in servaddr;

// Creating socket file descriptor

if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {

perror("socket creation failed");

exit(EXIT_FAILURE);

}

memset(&servaddr, 0, sizeof(servaddr));

// Filling server information

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(PORT);

servaddr.sin_addr.s_addr = INADDR_ANY;

socklen_t len = (socklen_t)sizeof(servaddr); //len is value/resuslt

// send msg

while (fgets(buffer, MAXLINE, stdin) != NULL) {

int i = strlen(buffer);

if (buffer[i - 1] == '\n') {

buffer[i - 1] = 0;

}

sendto(sockfd, (const char *)buffer, strlen(buffer), 0,

(const struct sockaddr *) &servaddr, len);

fprintf(stdout, "message: %s have sent.\n", buffer);

int n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL,

(struct sockaddr *) &servaddr, &len);

buffer[n] = '\0';

printf("Server : %s\n", buffer);

}

close(sockfd);

return 0;

}

情况1: 只运行客户端、不开启服务端

可以看见,没有响应,也发送不了数据。程序会一直阻塞在 recvfrom 上。

情况2: 先开启服务端,再开启客户端

也可以使用多个UDP客户端去和UDP服务器端通信,不再细述。

总结

UDP 是无连接的数据报程序,和 TCP 不同,不需要三次握手建立一条连接。UDP 程序通过 recvfrom 和 sendto 函数直接收发数据报报文。

reference

[1] 极客时间 · 网络编程实战 :06 | 嗨,别忘了UDP这个小兄弟

[2] UDP Server-Client implementation in C

Copyright © 2088 年度精选网游活动网 All Rights Reserved.
友情链接