1.题目1
编译运行UDP client/sever(https://www.geeksforgeeks.org/udp-server-client-implementation-c/),最好在不同的机器上运行,也可以在Linux上安装Linux虚拟机,或者买树莓派,并用wireshark抓包。
运行环境是在windows下的Ubuntu虚拟机和树莓派虚拟机。在一开始指定服务器的IP地址之后客户端接受的数据后面会出现乱码,而服务端则没有出现。对比两个之间的代码后发现客户端这边接受数据的代码部分中的函数recvfrom函数的最后一个参数的接收长度没有提前求出来,导致输出的时候把未用完的缓存的数组的空间也读取出来,所以就出现了乱码,修改之后就没有问题了。
可以看到,由于UDP是无连接的,客户端和服务端也只有两次通信来往,所以抓的包也是只有两次,其中服务端的IP地址是192.168.61.128,客户端的IP地址是192.168.61.129。
2.题目2
上面的程序利用send()和recv()分别代替sendto()和recvfrom()。提示:调用connect()函数,man一下,再搜索如何替代。代替前后的client端IP和port是谁创建的?是多少?
与之前的代码的区别主要是在调用send和recv之前利用connect函数连接两个主机便可以代替sendto和recvfrom。可知客户端的IP和port是由socket创建的,分别是192.168.31.128和38576。
3.源码
3.1服务端
// Server side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
#define MAXLINE 1024
// Driver code
int main()
{
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from server";
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);
}
//Filling client information
int len, n;
len = sizeof(cliaddr); //len is value/resuslt
n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, (struct sockaddr *)&cliaddr, &len);
buffer[n] = '\0';
printf("Client : %s\n", buffer);
sendto(sockfd, (const char *)hello, strlen(hello), MSG_CONFIRM, (struct sockaddr *)&cliaddr, len);
printf("Hello message sent.\n");
return 0;
}
3.2客户端
// Client side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
#define MAXLINE 1024
// Driver code
int main()
{
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from client";
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));
// Filling server information
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = inet_addr("192.168.61.131");
if (connect(sockfd, (struct sockaddr* )&servaddr,
sizeof(struct sockaddr_in)) < 0)
{
perror("socket");
exit(EXIT_FAILURE);
}
int n, len;
send(sockfd, (const char *)hello, strlen(hello), MSG_CONFIRM);
printf("Hello message sent.\n");
n = recv(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL);
buffer[n] = '\0';
printf("Server : %s\n", buffer);
close(sockfd);
return 0;
}