前言
为了更好的熟悉和掌握UDP通信以及使用UDP的相关函数接口,本期就和大家分享一个用UDP实现的一个在线下载器,分为server和client,服务器端负责接收请求以及发送用户需要的文件,用户需要发送请求命令进行请求的发送,服务器接收到后进行文件传输,用户端进行文件接收即可;
一、主要的功能
用UDP实现的一个在线下载器,分为server和client,服务器端负责接收请求以及发送用户需要的文件,用户需要发送请求命令进行请求的发送,服务器接收到后进行文件传输,用户端进行文件接收即可;
再来继续回顾一下udp编程的具体流程:
发送端:
(1)socket
(2)sendto
(3)recvfrom
接收端:
(1)socket
(2)bind
(3)recvfrom
(4)sendto 5
二、具体实现过程
2.1 流程图
第一步一定要着手理解清楚整个程序的脉络,理清楚程序的流程步骤,server的流程图如下:
client的流程图如下:
2.2 引入库
用到的头文件如下:
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#endif
2.3 Server
代码如下(示例):
#include "head.h"
struct sockaddr_in senaddr;
int bindOfIP(const char *pIp, int Port)
{
int sockfd = 0;
int ret = 0;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == sockfd)
{
perror("fail to sockfd");
return -1;
}
senaddr.sin_family = AF_INET;
senaddr.sin_port = htons(Port);
senaddr.sin_addr.s_addr = inet_addr(pIp);
ret = bind(sockfd, (struct sockaddr *)&senaddr, sizeof(senaddr));
if (-1 == ret)
{
perror("fail to bind");
return -1;
}
return sockfd;
}
int sendFile(char *filename, int sockfd, struct sockaddr *sendaddr, socklen_t len)
{
FILE *fp = NULL;
char tmpbuff[4096] = {0};
ssize_t ret = 0;
char *ptmp = NULL;
fp = fopen(filename, "r");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
printf("开始发送!\n");
while(1)
{
memset(tmpbuff, 0, sizeof(tmpbuff));
ret = fread(tmpbuff, 1, sizeof(tmpbuff), fp);
if (ret <= 0)
{
break;
}
printf("%s", tmpbuff);
ret = sendto(sockfd, tmpbuff, ret, 0, sendaddr, len);
if (-1 == ret)
{
perror("fail to sendto");
return -1;
}
}
memset(tmpbuff, 0, sizeof(tmpbuff));
sprintf(tmpbuff, "__quit__");
ret = sendto(sockfd, tmpbuff, ret, 0, sendaddr, len);
if (-1 == ret)
{
perror("fail to sendto");
return -1;
}
return 0;
}
int main(int argc, const char *argv[])
{
int sockfd = 0;
char filename[32] = {0};
ssize_t nsize = 0;
socklen_t len = sizeof(senaddr);
int ret = 0;
sockfd = bindOfIP("192.168.209.128", 50000);
while (1)
{
nsize = recvfrom(sockfd, filename, sizeof(filename), 0, (struct sockaddr *)&senaddr, &len);
if (-1 == nsize)
{
perror("fail to recvfrom");
return -1;
}
else
{
printf("请求的文件名和路径:filename = %s\n", filename);
ret = sendFile(filename, sockfd, (struct sockaddr *)&senaddr, len);
if (0 == ret)
{
printf("发送成功!\n");
}
}
}
return 0;
}
2.4 client
#include "head.h"
struct sockaddr_in recvbuf;
int recvFile(int sockfd, char *filename)
{
FILE *fp = NULL;
char tmpbuff[4096] = {0};
ssize_t nsize = 0;
//printf("进来了\n");
fp = fopen(filename, "w");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
while (1)
{
memset(tmpbuff, 0, sizeof(tmpbuff));
nsize = recvfrom(sockfd, tmpbuff, sizeof(tmpbuff), 0, NULL, NULL);
if (nsize <= 0)
{
break;
}
printf("%s", tmpbuff);
if (!strcmp("__quit__", tmpbuff))
{
break;
}
fwrite(tmpbuff, sizeof(char), nsize, fp);
fflush(fp);
}
fclose(fp);
return 0;
}
int main(int argc, const char *argv[])
{
int sockfd = 0;
char filename[32] = {0};
char *name = NULL;
ssize_t nsize = 0;
socklen_t len;
struct sockaddr_in senaddr;
int ret = 0;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == sockfd)
{
perror("fail to sockfd");
return -1;
}
senaddr.sin_family = AF_INET;
senaddr.sin_port = htons(50000);
senaddr.sin_addr.s_addr = inet_addr("192.168.209.128");
while (1)
{
printf("请输入您需要下载的文件路径:");
gets(filename);
nsize = sendto(sockfd, filename, strlen(filename), 0, (struct sockaddr *)&senaddr, sizeof(senaddr));
if (-1 == nsize)
{
perror("fail to sendto");
return -1;
}
name = filename + strlen(filename) - 1;
while (*name != '/')
{
--name;
}
++name;
printf("name = %s\n", name);
ret = recvFile(sockfd, name);
if (0 == ret)
{
printf("接收成功!\n");
break;
}
}
return 0;
}
总结
本期主要分享的是使用udp实现文件的传输下载,主要运用到的主要有UDP的相关函数接口,可以锻炼使用网络通信的思维;那么各位小伙伴一定要自己动手做一下,整个过程也是锻炼自己的一个过程,我也是在这样的过程中不断进步!
最后,各位小伙伴们如果喜欢我的分享可以点赞收藏哦,你们的认可是我创作的动力,一起加油!