📅  最后修改于: 2023-12-03 15:36:37.568000             🧑  作者: Mango
本程序使用UDP协议进行文件传输。UDP协议通常用于需要较少或没有错误检测和重发机制的应用程序中,如视频流传输、音频流传输等。
int sockfd;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket creating");
exit(EXIT_FAILURE);
}
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("bind server socket");
exit(EXIT_FAILURE);
}
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
char filename[MAX_FILENAME_LENGTH];
int filename_len;
size_t file_size;
int current_size;
// receive file request from client
filename_len = recvfrom(sockfd, filename, MAX_FILENAME_LENGTH, 0, (struct sockaddr*)&client_addr, &client_addr_len);
if (filename_len < 0) {
perror("filename receive");
exit(EXIT_FAILURE);
}
// open file for reading
FILE* fp = fopen(filename, "rb");
if (!fp) {
perror("file open");
exit(EXIT_FAILURE);
}
// get file size
fseek(fp, 0L, SEEK_END);
file_size = ftell(fp);
rewind(fp);
// send file size to client
if (sendto(sockfd, &file_size, sizeof(file_size), 0, (struct sockaddr*)&client_addr, client_addr_len) < 0) {
perror("file size send");
exit(EXIT_FAILURE);
}
int buffer_size = MIN(BUFFER_SIZE, file_size - current_size);
char buffer[buffer_size];
while (current_size < file_size) {
// read data from file
int bytes_read = fread(buffer, sizeof(char), buffer_size, fp);
if (bytes_read < 0) {
perror("file read");
exit(EXIT_FAILURE);
}
current_size += bytes_read;
// send data to client
if (sendto(sockfd, buffer, bytes_read, 0, (struct sockaddr*)&client_addr, client_addr_len) < 0) {
perror("file send");
exit(EXIT_FAILURE);
}
// update buffer size if necessary
buffer_size = MIN(BUFFER_SIZE, file_size - current_size);
}
fclose(fp);
close(sockfd);
完整的程序代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 12345
#define MAX_FILENAME_LENGTH 256
#define BUFFER_SIZE 4096
#define MIN(a, b) ((a) < (b) ? (a) : (b))
int main(int argc, char** argv) {
int sockfd;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket creating");
exit(EXIT_FAILURE);
}
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("bind server socket");
exit(EXIT_FAILURE);
}
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
char filename[MAX_FILENAME_LENGTH];
int filename_len;
size_t file_size;
int current_size;
// receive file request from client
filename_len = recvfrom(sockfd, filename, MAX_FILENAME_LENGTH, 0, (struct sockaddr*)&client_addr, &client_addr_len);
if (filename_len < 0) {
perror("filename receive");
exit(EXIT_FAILURE);
}
// open file for reading
FILE* fp = fopen(filename, "rb");
if (!fp) {
perror("file open");
exit(EXIT_FAILURE);
}
// get file size
fseek(fp, 0L, SEEK_END);
file_size = ftell(fp);
rewind(fp);
// send file size to client
if (sendto(sockfd, &file_size, sizeof(file_size), 0, (struct sockaddr*)&client_addr, client_addr_len) < 0) {
perror("file size send");
exit(EXIT_FAILURE);
}
// read and send file contents to client
int buffer_size = MIN(BUFFER_SIZE, file_size - current_size);
char buffer[buffer_size];
while (current_size < file_size) {
// read data from file
int bytes_read = fread(buffer, sizeof(char), buffer_size, fp);
if (bytes_read < 0) {
perror("file read");
exit(EXIT_FAILURE);
}
current_size += bytes_read;
// send data to client
if (sendto(sockfd, buffer, bytes_read, 0, (struct sockaddr*)&client_addr, client_addr_len) < 0) {
perror("file send");
exit(EXIT_FAILURE);
}
// update buffer size if necessary
buffer_size = MIN(BUFFER_SIZE, file_size - current_size);
}
fclose(fp);
close(sockfd);
return 0;
}