马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
第1关:UDP套接字创建与端口绑定
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <stdio.h>
- #include <errno.h>
- #include <string.h>
- /************************
- * port: 需要绑定的端口号
- * 返回值: 调用成功返回0,否则返回-1
- *************************/
- int UDPSocket(unsigned short port)
- {
- int ret = -1;
- /********** BEGIN **********/
- int sockfd;
- struct sockaddr_in server_addr;
- // 创建UDP套接字
- sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- if (sockfd == -1)
- {
- printf("创建UDP套接字失败: %s\n", strerror(errno));
- return -1;
- }
- // 初始化服务器地址结构体
- memset(&server_addr, 0, sizeof(server_addr));
- server_addr.sin_family = AF_INET;
- server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- server_addr.sin_port = htons(port);
- // 绑定端口
- ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
- if (ret == -1)
- {
- printf("绑定端口失败: %s\n", strerror(errno));
- close(sockfd);
- return -1;
- }
- ret = 0;
-
- /********** END **********/
-
- return ret;
- }
复制代码 第2关:UDP数据传送
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <stdio.h>
- #include <errno.h>
- #include <string.h>
- #include <unistd.h>
- #define PORT 8888
- int main()
- {
- int sockfd;
- sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- if(sockfd == -1)
- {
- return -1;
- }
- struct sockaddr_in addr;
- bzero(&addr, sizeof(addr)); //清空
- addr.sin_family = AF_INET;
- addr.sin_port = htons(PORT);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- //与PORT端口进行绑定
- if(bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
- {
- return -1;
- }
-
- char data[100];
- //接收客户端传来的数据,并打印出来(提示:换行打印)
- //同时将接收到的数据原样发送给客户端
- //当接收到"exit"字符串时,退出当前程序,不打印出"exit"字符串
- //提示:在每次接收字符串前要将存放字符串的变量清空
- /********** BEGIN **********/
- struct sockaddr_in clientAddr;
- socklen_t clientAddrLen = sizeof(clientAddr);
- while (1)
- {
- // 每次接收前清空存放字符串的变量
- memset(data, 0, sizeof(data));
- ssize_t recvLen = recvfrom(sockfd, data, sizeof(data), 0, (struct sockaddr *)&clientAddr, &clientAddrLen);
- if (recvLen == -1)
- {
- printf("接收数据失败: %s\n", strerror(errno));
- continue;
- }
- else if (recvLen > 0)
- {
- // 去掉字符串末尾可能的换行符等空白字符
- while (data[recvLen - 1] == '\n' || data[recvLen - 1] == '\r' || data[recvLen - 1] == '\t' || data[recvLen - 1] == ' ')
- {
- data[recvLen - 1] = '\0';
- recvLen--;
- }
- if (strcmp(data, "exit") == 0)
- {
- break;
- }
- // 换行打印接收到的数据
- printf("%s\n", data);
- // 将接收到的数据原样发送给客户端
- ssize_t sendLen = sendto(sockfd, data, recvLen, 0, (struct sockaddr *)&clientAddr, clientAddrLen);
- if (sendLen == -1)
- {
- printf("发送数据失败: %s\n", strerror(errno));
- }
- }
- }
-
- /********** END **********/
- close(sockfd);
-
- return 0;
- }
复制代码 第3关:项目实战
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <string.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- //定义数据块大小
- char data[16];
- //定义服务器端口和服务器地址
- #define PORT 8889
- #define SERVER_IP "127.0.0.1"
- int main(int argc, char *argv[])
- {
- int sockfd;
- sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- if(sockfd == -1)
- {
- return -1;
- }
- struct sockaddr_in servAddr;
- int servAddrLen = sizeof(servAddr);
- bzero(&servAddr, sizeof(servAddr));
- servAddr.sin_family = AF_INET;
- servAddr.sin_port = htons(PORT);
- servAddr.sin_addr.s_addr = inet_addr(SERVER_IP);
-
- //由用户传入的要下载文件的名称
- char *downLoadFileName = argv[1];
- printf("%s\n", argv[1]);
- //先在本地创建要下载的文件
- int fd = fd = open(downLoadFileName, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
- //向服务器发送要上传文件的名称
- sendto(sockfd, downLoadFileName, strlen(downLoadFileName), 0, (struct sockaddr *)&servAddr, servAddrLen);
-
- /********** BEGIN **********/
- char ack[16];
- int recvLen;
- // 循环接收服务器发送的数据块
- while (1)
- {
- // 接收服务器发送的数据块
- recvLen = recvfrom(sockfd, data, sizeof(data), 0, (struct sockaddr *)&servAddr, &servAddrLen);
- if (recvLen == -1)
- {
- printf("接收数据失败: %s\n", strerror(errno));
- continue;
- }
- // 根据数据块类型判断是否下载完成
- if (data[0] == 'e')
- {
- // 下载完成,关闭文件并退出程序
- close(fd);
- break;
- }
- else if (data[0] == 'c')
- {
- // 数据块为文件内容,将内容写入本地文件
- write(fd, &(data[1]), recvLen - 1);
- }
- // 向服务器发送接收确认请求
- sendto(sockfd, "OK", strlen("OK"), 0, (struct sockaddr *)&servAddr, servAddrLen);
- // 清空数据块数据部分(除了类型标识字节)
- memset(&(data[1]), 0, sizeof(data) - 1);
- }
-
- /********** END **********/
-
- close(sockfd);
-
- return 0;
- }
复制代码 |