As opposed to TCP, UDP is a non-connected, unreliable transport protocol.
If we want to use UDP to achieve reliable transmission, we need to solve two problems: packet loss and post-send first (packet order).
Workaround:
1) The packet number, according to the order of the packet received and stored;
2) The receiving end receives the packet to send the acknowledgment message to the sending side, the sending side receives the confirmation data to continue to send the next packet, if the receiving end receives the packet the number is not the expected number, then asks the sending side to resend.
Here is an example program:
The program defines a package structure, which contains data and headers, the header contains the package number and data size, after testing, the program can successfully transfer a video file.
The specific implementation code is as follows:
The 1.server terminal code is as follows:
#include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> # include<arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include < netdb.h> #include <stdarg.h> #include <string.h> #define SERVER_PORT 8000 #define BUFFER_SIZE 1024x768 #def
INE file_name_max_size 512/* Baotou */typedef struct {int id;
int buf_size;
}packinfo;
/* Receive package */struct Sendpack {packinfo head;
Char Buf[buffer_size];
} data;
int main () {/* Send ID */int send_id = 0;
/* Receive ID */int receive_id = 0;
/* Create a UDP socket interface */struct sockaddr_in server_addr;
Bzero (&server_addr, sizeof (SERVER_ADDR));
server_addr.sin_family = af_inet;
SERVER_ADDR.SIN_ADDR.S_ADDR = htonl (Inaddr_any);
Server_addr.sin_port = htons (Server_port);
/* Create socket */int SERVER_SOCKET_FD = socket (af_inet, SOCK_DGRAM, 0); if (server_socket_fd = =-1) {perror ("Create socket Failed:");
Exit (1); }/* Bound socket interface */if ( -1 = = (bind (server_socket_fd, struct sockaddr*) &server_addr,sizeof (SERVER_ADDR))) {PE
Rror ("Server Bind Failed:");
Exit (1);
}/* Data transfer */while (1) {/* Defines an address for capturing client address */struct sockaddr_in client_addr;
socklen_t client_addr_length = sizeof (CLIENT_ADDR);
/* Receive data */char buffer[buffer_size];
Bzero (buffer, buffer_size); if (Recvfrom (server_socket_fd, buffer, buffer_size,0, (struct sockaddr*) &client_addr, &client_addr_length) = =
-1) {perror ("Receive Data Failed:");
Exit (1);
}/* Copy from buffer file_name */char file_name[file_name_max_size+1];
Bzero (file_name,file_name_max_size+1); strncpy (file_name, buffer, strlen (buffer) >file_name_max_size?
File_name_max_size:strlen (buffer));
printf ("%s\n", file_name);
/* Open Files */File *FP = fopen (file_name, "R"); if (NULL = = fp) {printf ("file:%s not found.\n", File_NAME);
} else {int len = 0;
/* Each time a piece of data is read, it is sent to the client */while (1) {Packinfo pack_info;
if (receive_id = = send_id) {++send_id; if (len = fread (data.buf, sizeof (char), buffer_size, FP)) > 0) {data.head.id = send_id;/* Send I D put into the header for marking order */data.head.buf_size = len; /* Record Data length */if (SendTo (SERVER_SOCKET_FD, (char*) &data, sizeof (data), 0, (struct sockaddr*) &client_addr
, client_addr_length) < 0) {perror ("Send File Failed:");
Break }/* Receive confirmation message */Recvfrom (SERVER_SOCKET_FD, (char*) &pack_info, sizeof (Pack_info), 0, (struct so
ckaddr*) &client_addr, &client_addr_length);
receive_id = pack_info.id;
} else {break;
}} else {/* If the received ID is not the same as the sent ID, Resend */ if (SendTo (SERVER_SOCKET_FD, (char*) &data, sizeof (data), 0, (struct sockaddr*) &client_addr, Client_addr_le
Ngth) < 0) {perror ("Send File Failed:");
Break }/* Receive confirmation message */Recvfrom (SERVER_SOCKET_FD, (char*) &pack_info, sizeof (Pack_info), 0, (struct SOCKAD
dr*) &client_addr, &client_addr_length);
receive_id = pack_info.id;
} */* Close file */fclose (FP);
printf ("file:%s Transfer successful!\n", file_name);
}} close (SERVER_SOCKET_FD);
return 0; }
The
2.client Terminal code is as follows:
#include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> # include<arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include < netdb.h> #include <stdarg.h> #include <string.h> #define SERVER_PORT 8000 #define BUFFER_SIZE 1024x768 #def
INE file_name_max_size 512/* Baotou */typedef struct {int id;
int buf_size;
}packinfo;
/* Receive package */struct Recvpack {packinfo head;
Char Buf[buffer_size];
} data;
int main () {int id = 1;
/* Server address */struct sockaddr_in server_addr;
Bzero (&server_addr, sizeof (SERVER_ADDR));
server_addr.sin_family = af_inet;
SERVER_ADDR.SIN_ADDR.S_ADDR = inet_addr ("127.0.0.1");
Server_addr.sin_port = htons (Server_port);
socklen_t server_addr_length = sizeof (SERVER_ADDR);
/* Create socket */int CLIENT_SOCKET_FD = socket (af_inet, SOCK_DGRAM, 0); if (CLIENT_SOCKET_FD < 0) {perror ("Create socket Failed: ");
Exit (1);
}/* Enter file name to buffer */char file_name[file_name_max_size+1];
Bzero (file_name, file_name_max_size+1);
printf ("Please Input File Name on Server:");
scanf ("%s", file_name);
Char Buffer[buffer_size];
Bzero (buffer, buffer_size); strncpy (buffer, file_name, strlen (file_name) >buffer_size?
Buffer_size:strlen (file_name)); /* Send file name */if (SendTo (client_socket_fd,buffer,buffer_size,0, (struct sockaddr*) &server_addr,server_addr_length)
< 0) {perror ("Send File Name Failed:");
Exit (1);
}/* Open file, ready to write */File *FP = fopen (file_name, "w");
if (NULL = = fp) {printf ("file:\t%s Can not Open to write\n", file_name);
Exit (1);
}/* Receives data from the server and writes the file */int len = 0;
while (1) {Packinfo pack_info; if (len = Recvfrom (client_socket_fd, (char*) &data, sizeof (data), 0, (struct sockaddr*) &server_addr,&
server_addr_length)) > 0) {if (data.head.id = = ID) {Pack_info.id = data.head.id;
Pack_info.buf_size = data.head.buf_size;
++id; /* Send packet Confirmation message */if (SendTo (CLIENT_SOCKET_FD, (char*) &pack_info, sizeof (Pack_info), 0, (struct sockaddr*) &se
RVER_ADDR, Server_addr_length) < 0) {printf ("Send Confirm information failed!");
}/* Write file */if (fwrite (data.buf, sizeof (char), data.head.buf_size, FP) < data.head.buf_size)
{printf ("file:\t%s Write failed\n", file_name);
Break
}} else if (Data.head.id < ID)/* If it is a re-sent package */{pack_info.id = data.head.id;
Pack_info.buf_size = data.head.buf_size; /* Re-send packet acknowledgement */if (SendTo (CLIENT_SOCKET_FD, (char*) &pack_info, sizeof (Pack_info), 0, (struct sockaddr*) &se
RVER_ADDR, Server_addr_length) < 0) {printf ("Send Confirm information failed!");
}} else {}} else {break;
}} printf ("Receive file:\t%s from Server IP successful!\n", file_name);
Fclose (FP);
Close (CLIENT_SOCKET_FD);
return 0;
}