使用UDP套接字
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
ssize_t numBytesRcvd = recvfrom(sock, buffer, MAXSTRINGLENGTH, 0, (struct sockaddr *) &clntAddr, &clntAddrLen);
if (numBytesRcvd < 0) DieWithSystemMessage("recvfrom() failed");
6
struct addrinfo addrCriteria; memset(&addrCriteria, 0, sizeof(addrCriteria)); addrCriteria.ai_family = AF_UNSPEC; addrCriteria.ai_socktype = SOCK_DGRAM; addrCriteria.ai_protocol = IPPROTO_UDP; struct addrinfo *servAddr; int rtnVal = getaddrinfo(server, servPort, &addrCriteria, &servAddr); if (rtnVal != 0) DieWithUserMessage("getaddrinfo() failed", gai_strerror(rtnVal)); int sock = socket(servAddr->ai_family, servAddr>ai_socktype, servAddr->ai_protocol); if (sock < 0) DieWithSystemMessage("socket() failed");
4
UDP客户
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netdb.h> #include "Practical.h" int main(int argc, char *argv[]) {
if (!SockAddrsEqual(servAddr->ai_addr, (struct sockaddr *) &fromAddr)) DieWithUserMessage("recvfrom()", "received a packet from unknown source"); freeaddrinfo(servAddr); buffer[echoStringLen] = '\0'; printf("Received: %s\n", buffer); close(sock); exit(0);
通信应用软件设计
第四章
使用UDPΒιβλιοθήκη Baidu接字
目标
掌握UDP套接字的基本概念 掌握编写通用的UDP程序 掌握UDP的connect的特点以及函数sendto 和recvfrom。
2
概述
UDP(User Datagram Protocol)提供了 比TCP更简单的端到端服务。 UDP的两个主要功能:向IP层添加了另一 个寻址(端口)层;检测所收到的数据是 否损坏,并丢弃任何损坏的数据报。
struct sockaddr_storage fromAddr; socklen_t fromAddrLen = sizeof(fromAddr); char buffer[MAXSTRINGLENGTH + 1]; numBytes = recvfrom(sock, buffer, MAXSTRINGLENGTH, 0, (struct sockaddr *) &fromAddr, &fromAddrLen);
3
UDP与TCP之间的区别
UDP套接字在使用前不必进行连接。TCP 类似于电话通信,而UDP类似于邮件通信。 UDP与TCP处理消息边界的方式不同: UDP套接字保留接收字符边界,而TCP则 不会保留接收字符边界。 UDP提供的端到端传输服务是一种“尽力 而为”的服务:不保证通过UDP套接字发 送的消息会准确地达到目的地,即存在丢 失。
11
if (sock < 0) DieWithSystemMessage("socket() failed"); if (bind(sock, servAddr->ai_addr, servAddr>ai_addrlen) < 0) DieWithSystemMessage("bind() failed");
sendto的前四个参数与send相同,另两个 指定了消息的目的地址。 类似的recvfrom的参数也与recv基本相同, 后两个参数指定了所接收到的数据报来源。 一般情况下,一次recvfrom会接收完一次 sendto所发送的所有数据。 在UDP套接字上可以由recvfrom接收的最 大数据量为65507字节。
if (numBytesSent < 0) DieWithSystemMessage("sendto() failed)"); else if (numBytesSent != numBytesRcvd) DieWithUserMessage("sendto()", "sent unexpected number of bytes"); } 14
16
连接UDP套接字
在UDP套接字上调用connect来固定需要发 送的目的地址。 UDP使用connect并不表示真正连接,只是 告诉低层TCP/IP模块,自己所要发送和接 收的数据目的地和来源。这时可以使用 send和recv来代替sendto和recvfrom函数。 在UDP套接字上使用connect()函数的一个 好处是:允许接收由套接字上以前动作产 生的错误。
fputs("Handling client ", stdout); PrintSocketAddress((struct sockaddr *) &clntAddr, stdout); fputc('\n', stdout);
13
ssize_t numBytesSent = sendto(sock, buffer, numBytesRcvd, 0, (struct sockaddr *) &clntAddr, sizeof(clntAddr));
if (argc != 2) DieWithUserMessage("Parameter(s)", "<Server Port/Service>");
char *service = argv[1];
10
struct addrinfo addrCriteria; memset(&addrCriteria, 0, sizeof(addrCriteria)); addrCriteria.ai_family = AF_UNSPEC; addrCriteria.ai_flags = AI_PASSIVE; addrCriteria.ai_socktype = SOCK_DGRAM; addrCriteria.ai_protocol = IPPROTO_UDP; struct addrinfo *servAddr; int rtnVal = getaddrinfo(NULL, service, &addrCriteria, &servAddr); if (rtnVal != 0) DieWithUserMessage("getaddrinfo() failed", gai_strerror(rtnVal)); int sock = socket(servAddr->ai_family, servAddr>ai_socktype, servAddr->ai_protocol);
size_t echoStringLen = strlen(echoString); if (echoStringLen > MAXSTRINGLENGTH) DieWithUserMessage(echoString, "string too long");
char *servPort = (argc == 4) ? argv[3] : "echo";
getaddrinfo() freeaddrinfo(servAddr); for (;;) { struct sockaddr_storage clntAddr; socklen_t clntAddrLen = sizeof(clntAddr);12
char buffer[MAXSTRINGLENGTH];
17
7
ssize_t numBytes = sendto(sock, echoString, echoStringLen, 0, servAddr->ai_addr, servAddr->ai_addrlen); if (numBytes < 0) DieWithSystemMessage("sendto() failed"); else if (numBytes != echoStringLen) DieWithUserMessage("sendto() error", "sent unexpected number of bytes");
5
if (argc < 3 || argc > 4) DieWithUserMessage("Parameter(s)", "<Server Address/Name> <Echo Word> [<Server Port/Service>]");
char *server = argv[1]; char *echoString = argv[2]; /
}
9
UDP服务器
#include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include "Practical.h" int main(int argc, char *argv[]) {
8
if (numBytes < 0) DieWithSystemMessage("recvfrom() failed"); else if (numBytes != echoStringLen) DieWithUserMessage("recvfrom() error", "received unexpected number of bytes");
利用UDP套接字进行发送和接收
一旦创建了UDP套接字,就可以使用它来 向任何地址发送/接收来自任何地址的消息 使用函数 ssize_t sendto(int socket,const void *,msg, size_t msglength,int flags,const struct sockaddr *destaddr,socklen_t addrlen) ssize_t recvfrom(int socket,const void *,msg, size_t msglength,int flags,const 15 struct sockaddr *destaddr,socklen_t
if (numBytesRcvd < 0) DieWithSystemMessage("recvfrom() failed");
6
struct addrinfo addrCriteria; memset(&addrCriteria, 0, sizeof(addrCriteria)); addrCriteria.ai_family = AF_UNSPEC; addrCriteria.ai_socktype = SOCK_DGRAM; addrCriteria.ai_protocol = IPPROTO_UDP; struct addrinfo *servAddr; int rtnVal = getaddrinfo(server, servPort, &addrCriteria, &servAddr); if (rtnVal != 0) DieWithUserMessage("getaddrinfo() failed", gai_strerror(rtnVal)); int sock = socket(servAddr->ai_family, servAddr>ai_socktype, servAddr->ai_protocol); if (sock < 0) DieWithSystemMessage("socket() failed");
4
UDP客户
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netdb.h> #include "Practical.h" int main(int argc, char *argv[]) {
if (!SockAddrsEqual(servAddr->ai_addr, (struct sockaddr *) &fromAddr)) DieWithUserMessage("recvfrom()", "received a packet from unknown source"); freeaddrinfo(servAddr); buffer[echoStringLen] = '\0'; printf("Received: %s\n", buffer); close(sock); exit(0);
通信应用软件设计
第四章
使用UDPΒιβλιοθήκη Baidu接字
目标
掌握UDP套接字的基本概念 掌握编写通用的UDP程序 掌握UDP的connect的特点以及函数sendto 和recvfrom。
2
概述
UDP(User Datagram Protocol)提供了 比TCP更简单的端到端服务。 UDP的两个主要功能:向IP层添加了另一 个寻址(端口)层;检测所收到的数据是 否损坏,并丢弃任何损坏的数据报。
struct sockaddr_storage fromAddr; socklen_t fromAddrLen = sizeof(fromAddr); char buffer[MAXSTRINGLENGTH + 1]; numBytes = recvfrom(sock, buffer, MAXSTRINGLENGTH, 0, (struct sockaddr *) &fromAddr, &fromAddrLen);
3
UDP与TCP之间的区别
UDP套接字在使用前不必进行连接。TCP 类似于电话通信,而UDP类似于邮件通信。 UDP与TCP处理消息边界的方式不同: UDP套接字保留接收字符边界,而TCP则 不会保留接收字符边界。 UDP提供的端到端传输服务是一种“尽力 而为”的服务:不保证通过UDP套接字发 送的消息会准确地达到目的地,即存在丢 失。
11
if (sock < 0) DieWithSystemMessage("socket() failed"); if (bind(sock, servAddr->ai_addr, servAddr>ai_addrlen) < 0) DieWithSystemMessage("bind() failed");
sendto的前四个参数与send相同,另两个 指定了消息的目的地址。 类似的recvfrom的参数也与recv基本相同, 后两个参数指定了所接收到的数据报来源。 一般情况下,一次recvfrom会接收完一次 sendto所发送的所有数据。 在UDP套接字上可以由recvfrom接收的最 大数据量为65507字节。
if (numBytesSent < 0) DieWithSystemMessage("sendto() failed)"); else if (numBytesSent != numBytesRcvd) DieWithUserMessage("sendto()", "sent unexpected number of bytes"); } 14
16
连接UDP套接字
在UDP套接字上调用connect来固定需要发 送的目的地址。 UDP使用connect并不表示真正连接,只是 告诉低层TCP/IP模块,自己所要发送和接 收的数据目的地和来源。这时可以使用 send和recv来代替sendto和recvfrom函数。 在UDP套接字上使用connect()函数的一个 好处是:允许接收由套接字上以前动作产 生的错误。
fputs("Handling client ", stdout); PrintSocketAddress((struct sockaddr *) &clntAddr, stdout); fputc('\n', stdout);
13
ssize_t numBytesSent = sendto(sock, buffer, numBytesRcvd, 0, (struct sockaddr *) &clntAddr, sizeof(clntAddr));
if (argc != 2) DieWithUserMessage("Parameter(s)", "<Server Port/Service>");
char *service = argv[1];
10
struct addrinfo addrCriteria; memset(&addrCriteria, 0, sizeof(addrCriteria)); addrCriteria.ai_family = AF_UNSPEC; addrCriteria.ai_flags = AI_PASSIVE; addrCriteria.ai_socktype = SOCK_DGRAM; addrCriteria.ai_protocol = IPPROTO_UDP; struct addrinfo *servAddr; int rtnVal = getaddrinfo(NULL, service, &addrCriteria, &servAddr); if (rtnVal != 0) DieWithUserMessage("getaddrinfo() failed", gai_strerror(rtnVal)); int sock = socket(servAddr->ai_family, servAddr>ai_socktype, servAddr->ai_protocol);
size_t echoStringLen = strlen(echoString); if (echoStringLen > MAXSTRINGLENGTH) DieWithUserMessage(echoString, "string too long");
char *servPort = (argc == 4) ? argv[3] : "echo";
getaddrinfo() freeaddrinfo(servAddr); for (;;) { struct sockaddr_storage clntAddr; socklen_t clntAddrLen = sizeof(clntAddr);12
char buffer[MAXSTRINGLENGTH];
17
7
ssize_t numBytes = sendto(sock, echoString, echoStringLen, 0, servAddr->ai_addr, servAddr->ai_addrlen); if (numBytes < 0) DieWithSystemMessage("sendto() failed"); else if (numBytes != echoStringLen) DieWithUserMessage("sendto() error", "sent unexpected number of bytes");
5
if (argc < 3 || argc > 4) DieWithUserMessage("Parameter(s)", "<Server Address/Name> <Echo Word> [<Server Port/Service>]");
char *server = argv[1]; char *echoString = argv[2]; /
}
9
UDP服务器
#include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include "Practical.h" int main(int argc, char *argv[]) {
8
if (numBytes < 0) DieWithSystemMessage("recvfrom() failed"); else if (numBytes != echoStringLen) DieWithUserMessage("recvfrom() error", "received unexpected number of bytes");
利用UDP套接字进行发送和接收
一旦创建了UDP套接字,就可以使用它来 向任何地址发送/接收来自任何地址的消息 使用函数 ssize_t sendto(int socket,const void *,msg, size_t msglength,int flags,const struct sockaddr *destaddr,socklen_t addrlen) ssize_t recvfrom(int socket,const void *,msg, size_t msglength,int flags,const 15 struct sockaddr *destaddr,socklen_t