Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
1 UDP network programming
1.1 process
Server:
- Create socket socket()
- Fill in the server network information struct sockaddr_in
- Bind () bind the socket to the server network information structure
- Communicate recvfrom()/sendto()
Client:
- Create socket socket()
- Fill in the server network information struct sockaddr_in
- Communicate recvfrom()/sendto()
1.2 recvfrom ()/sendto ()
1 — recvfrom()
- The header file:
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
- Function: Receives data
- Parameters:
-
Sockfd: indicates the file descriptor
- Server: Return value of Accept
- Client: return value of the socket
-
Buf: saves the received data
-
Len: The number of bytes to receive theoretically
-
Flags: indicates the flag bit
-
0 block
-
The MSG_DONTWAIT non-blocking
-
-
Src_addr: the address of the source, whose data is received, and whose information is automatically populated with this parameter
-
Addrlen: indicates the size of src_ADDR
-
- The return value:
- Success: Number of bytes actually received
- Failure: 1
2 — sendto()
- The header file:
#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
- Function: Send data
- Parameters:
-
Sockfd: indicates the file descriptor
- Server: Return value of Accept
- Client: return value of the socket
-
Buf: data to be sent
-
Len: The theoretical number of bytes to send
-
Flags: indicates the flag bit
-
0 block
-
The MSG_DONTWAIT non-blocking
-
-
Dest_addr: specifies the destination address
-
Addrlen: specifies the size of dest_addr
-
- The return value:
- Success: number of bytes sent
- Failure: 1
1.3 Code (two demos)
1.3.1 server
//UDP network programming server
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <string.h>
#define N 128
#defineERRLOG(errmsg) do{\ perror(errmsg); \ printf("%s - %s - %d\n", __FILE__, __func__, __LINE__); \ exit(1); \ }while(0)
int main(int argc, char const *argv[])
{
if(argc < 3)
{
fprintf(stderr."Usage: %s <ip> <port>\n", argv[0]);
exit(1);
}
int sockfd;
struct sockaddr_in serveraddr.clientaddr;
socklen_t addrlen = sizeof(serveraddr);
char buf[N] = {0};
// Step 1: Create a socket
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) = =- 1)
{
ERRLOG("socket error");
}
// Step 2: Populate the server network information structure
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
// Step 3: bind the socket to the server network information structure
if(bind(sockfd, (struct sockaddr *)&serveraddr, addrlen) == - 1)
{
ERRLOG("bind error");
}
// Communicate
while(1)
{
NEXT:
if(recvfrom(sockfd, buf, N, 0, (struct sockaddr *)&clientaddr, &addrlen) == - 1)
{
ERRLOG("recvfrom error");
}
if(strcmp(buf, "quit") = =0)
{
printf("Client %s-%d exited \n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
goto NEXT;
}
printf("% s % d: % s \ n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), buf);
strcat(buf, "^_^");
if(sendto(sockfd, buf, N, 0, (struct sockaddr *)&clientaddr, addrlen) == - 1)
{
ERRLOG("sendto error"); }}return 0;
}
Copy the code
1.3.2 the client
//UDP network programming client
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <string.h>
#define N 128
#defineERRLOG(errmsg) do{\ perror(errmsg); \ printf("%s - %s - %d\n", __FILE__, __func__, __LINE__); \ exit(1); \ }while(0)
int main(int argc, char const *argv[])
{
if(argc < 3)
{
fprintf(stderr."Usage: %s <ip> <port>\n", argv[0]);
exit(1);
}
int sockfd;
struct sockaddr_in serveraddr;
socklen_t addrlen = sizeof(serveraddr);
// Step 1: Create a socket
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) = =- 1)
{
ERRLOG("socket error");
}
// Step 2: Populate the server network information structure
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
// Communicate
char buf[N] = {0};
while(1)
{
fgets(buf, N, stdin);
buf[strlen(buf) - 1] = '\ 0';
if(sendto(sockfd, buf, N, 0, (struct sockaddr *)&serveraddr, addrlen) == - 1)
{
ERRLOG("sendto error");
}
if(strcmp(buf, "quit") = =0)
{
printf("Client exits \n");
exit(0);
}
memset(buf, 0, N);
if(recvfrom(sockfd, buf, N, 0, (struct sockaddr *)&serveraddr, &addrlen) == - 1)
{
ERRLOG("recvfrom error");
}
printf("Server: %s\n", buf);
}
return 0;
}
Copy the code
2 TFTP protocol based on UDP
2.1 Basic Concepts
TFTP: == Simple file transfer protocol ==
Originally used to boot diskless systems, it was designed to transfer small files
Features:
- Based on UDP protocol implementation
- User validity authentication is not performed
Data transmission mode:
- Octet: indicates the binary mode
- Netascii: text mode
- Mail: No longer supported
2.2 Client File Download Communication Process
First of all, the client will send a message to the server to inform the service that I want to download. The first message sent is the request instruction. Note that the fixed == port number is 69==.
The server returns a packet to the client, [numbered, size, and content (512) (default)]
After receiving the data packet, the client receives the data packet and writes the contents of 512 files to the specified file. After receiving the data, the client sends a reply packet to the server. The serial number is the same as that of the received data packet.
Then the correspondence continued;
Until less than 512 packets have been sent,
Summary of TFTP Communication Process (no option)
- The server is waiting for a client request on port 69
- If the server approves the request, it communicates with the client using a temporary port
- The number of each packet changes (starting from 1)
- Each packet is acknowledged by an ACK, and if a timeout occurs, the last packet (data or ACK) needs to be resent
- Data is transmitted in 512 bytes
- Data smaller than 512 bytes indicates the end of transmission
2.3 Protocol Analysis
Note that the client downloads the file read, and the server uses the opcode to distinguish between requests
Read/write request: For example, if the operation code is 1, download + file name +0 interval + mode (eg: OCTET) +0 indicates the end.
Error code:
- 0 is not defined. See Error message
- 1 File not found.
- 2 Access violation.
- 3 Disk full or allocation exceeded.
- 4 illegal TFTP operation.
- 5 Unknown transfer ID.
- 6 File already exists.
- 7 No such user.
- 8 Unsupported option(s) requested.
2.4 Downloading function Package and Receiving Data and Parsing by TFTP Client (Demo)
Maximum download 32M, 65535*
//UDP network programming client
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <string.h>
#define N 128
#defineERRLOG(errmsg) do{\ perror(errmsg); \ printf("%s - %s - %d\n", __FILE__, __func__, __LINE__); \ exit(1); \ }while(0)
int main(int argc, char const *argv[])
{
if(argc < 3)
{
fprintf(stderr."Usage: %s <ip> <port>\n", argv[0]);
exit(1);
}
int sockfd;
struct sockaddr_in serveraddr;
socklen_t addrlen = sizeof(serveraddr);
// Step 1: Create a socket
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) = =- 1)
{
ERRLOG("socket error");
}
// Step 2: Populate the server network information structure
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));
char filename[32] = {0};
printf("Please enter the file name to download:");
scanf("%s", filename);
// The TFTP client implements the download function
// The package sends the data to the server and tells it to download
// If you define a structure, the filename is indeterminate
unsigned char buf[600] = {0};/ / packet
int n;// The number of bytes in the packet
unsigned short code;/ / sent wrong words.if
unsigned short num;/ / block number
unsigned char text[600] = {0};// Store the content
ssize_t bytes;// The number of bytes to receive, up to 516
// Opcode assignment
// Method 1: cast two bytes of space and assign the value of the network byte order
//*(unsigned short *)buf = htons(1);
// Method 2: Split the data into one byte units, so you don't need to worry about byte order
//buf[0] = 0;
//buf[1] = 1;
/ / set package:
n = sprintf(buf, "%c%c%s%c%s%c".0.1, filename, 0."octet".0);
// Send data to the server
if(sendto(sockfd, buf, n, 0, (struct sockaddr *)&serveraddr, addrlen) == - 1)
{
ERRLOG("sendto error");
}
// Receive data
memset(buf, 0.600);
if((bytes = recvfrom(sockfd, buf, 600.0, (struct sockaddr *)&serveraddr, &addrlen)) == - 1)
{
ERRLOG("recvfrom error");
}
// Parse the packet
//buf is the entire data, which is then parsed in segments
/ / operation code
code = ntohs(*(unsigned short *)buf);
// Block number or error code
num = ntohs(*(unsigned short *)(buf+2));
// File contents or error information
strncpy(text, buf+4, bytes4 -);// Intercepts 512 packets
printf("code:%d, num:%d\n", code, num);
printf("%s\n", text);
return 0;
}
Copy the code