This article is very detailed, and it also talks about how to use the network debugging assistant. From this point of view, it is really simple to write.
Reprinted from: https://blog.csdn.net/qq_38113006/article/details/105531439
C language network programming (1) - UDP communication
Willliam_william 2020-04-15 13:56:37 1465
Category column: C language network programming
copyright
C language network programming (1) - UDP communication
1, socket
If we want to carry out network communication, we need to use socket. Socket is the network socket. Applications can send or receive data through it, and can open, read, write and close it like files.
In C language, there is a library supporting sockets. You can create a socket object by using the socket() function in the library. The prototype of the socket() function is
int socket(int domain, int type, int protocol);
- The domain parameter refers to the protocol domain, also known as the protocol family. The commonly used protocol families are AF_INET,AF_ Inet6,... Etc., AF_INET refers to ipv4, AF_INET6 is ipv6;
- Then type, which specifies the socket type with SOCK_STREAM (streaming socket, mainly used for TCP protocol) and SOCK_DGRAM (datagram socket, mainly used for UDP protocol), etc;
- Protocol is the specified protocol. The commonly used protocols are IPPROTO_TCP,IPPTOTO_UDP,IPPROTO_SCTP,IPPROTO_TIPC, etc. they correspond to TCP transmission protocol, UDP transmission protocol, STCP transmission protocol and TIPC transmission protocol respectively, but type and proto cannot be combined at will. When the protocol parameter is 0, the default protocol corresponding to type will be automatically selected.
2, UDP send data
First, we add the header file to use
#include <stdio.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <unistd.h>
Create a udp socket, ipv4 protocol, and use sock_ If the Dgram parameter protocol is 0, the udp protocol will be automatically selected by default;
// 1. Use the socket() function to get a socket file descriptor int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
Then we put the ip address and port number of the end to receive data in a structure
// 2. Prepare the address and port of the receiver, '192.168.0.107' represents the destination ip address and 8080 represents the destination port number struct sockaddr_in sock_addr = {0}; sock_addr.sin_family = AF_INET; // Set the address family to IPv4 sock_addr.sin_port = htons(8266); // Set the port number information of the address sock_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); //Set IP address
When you are ready, you can use the SendTo function to send. For the sendto() function, the number of characters actually transmitted is returned if successful, and - 1 if failed,
// 3. Send data to the specified ip and port char sendbuf[]={"hello world."}; ret = sendto(sockfd, sendbuf, sizeof(sendbuf), 0, (struct sockaddr*)&sock_addr, sizeof(sock_addr));
After sending, you can close the socket
// 4. Close the socket close(sockfd);
Open the network debugging assistant, compile and run the program. You can see that the data is sent successfully and the network debugging assistant has received the data,
Note that if you don't run python program on the local windows system and run it on the Ubuntu virtual machine or other machines in the LAN, you should turn off the firewall of windows and say the important things three times!!!
Note that if you don't run python program on the local windows system and run it on the Ubuntu virtual machine or other machines in the LAN, you should turn off the firewall of windows and say the important things three times!!!
Note that if you don't run python program on the local windows system and run it on the Ubuntu virtual machine or other machines in the LAN, you should turn off the firewall of windows and say the important things three times!!!
Then we let it send it every second, send it 10 times, and send it successfully
Attach complete code:
#include <stdio.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <unistd.h> int main(void) { int ret = -1; // 1. Use the socket() function to get a socket file descriptor int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (-1 == sockfd) { printf("socket open err."); return -1; } // 2. Prepare the address and port of the receiver, '192.168.0.107' represents the destination ip address and 8266 represents the destination port number struct sockaddr_in sock_addr = {0}; sock_addr.sin_family = AF_INET; // Set the address family to IPv4 sock_addr.sin_port = htons(8266); // Set the port number information of the address sock_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); //Set IP address // 3. Send data to the specified ip and port char sendbuf[]={"hello world, I am UDP."}; int cnt = 10; while(cnt--) { ret = sendto(sockfd, sendbuf, sizeof(sendbuf), 0, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); printf("ret = %d \n",ret); sleep(1); } // 4. Close the socket close(sockfd); }
3, UDP receive data
When sending data before, we can see that the port number is changing all the time, so we need to know what the port number is to receive data, so we need to fix a port number first and use the bind function
// 2. Bind local related information. If not, the system will randomly assign a port number struct sockaddr_in local_addr = {0}; local_addr.sin_family = AF_INET; //Use IPv4 address local_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); //Native IP address local_addr.sin_port = htons(12341); //port bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));//Bind socket to IP and port
recvfrom function is used for receiving data. The first parameter is the socket file descriptor, the second parameter is the receiving buffer, the third parameter is the maximum received data length, the fourth parameter is generally zero, and the fifth parameter is the address and port information of the other party sending data;
// 3. Waiting to receive the data sent by the other party struct sockaddr_in recv_addr; socklen_t addrlen = sizeof(recv_addr); char recvbuf[1024] = {0}; ret = recvfrom(sockfd, recvbuf, 1024, 0,(struct sockaddr*)&recv_addr,&addrlen); //1024 indicates the maximum number of bytes received this time
Print it out after receiving:
printf("[recv from %s:%d]%s \n",inet_ntoa(*(struct in_addr*)&recv_addr.sin_addr.s_addr),ntohs(recv_addr.sin_port),recvbuf);
Operation results:
Attach complete code:
#include <stdio.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <unistd.h> int main(void) { int ret = -1; // 1. Use the socket() function to get a socket file descriptor int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (-1 == sockfd) { printf("socket open err."); return -1; } // 2. Bind local related information. If not, the system will randomly assign a port number struct sockaddr_in local_addr = {0}; local_addr.sin_family = AF_INET; //Use IPv4 address local_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); //Native IP address local_addr.sin_port = htons(12341); //port bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));//Bind socket to IP and port // 3. Waiting to receive the data sent by the other party struct sockaddr_in recv_addr; socklen_t addrlen = sizeof(recv_addr); char recvbuf[1024] = {0}; ret = recvfrom(sockfd, recvbuf, 1024, 0,(struct sockaddr*)&recv_addr,&addrlen); //1024 indicates the maximum number of bytes received this time printf("[recv from %s:%d]%s \n",inet_ntoa(*(struct in_addr*)&recv_addr.sin_addr.s_addr),ntohs(recv_addr.sin_port),recvbuf); // 4. Close the socket close(sockfd); }
4, UDP sending and receiving data
Realize such a function, send messages 10 times through UDP, wait for reception, and print the received data and its source:
Completion code:
#include <stdio.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <unistd.h> int main(void) { int ret = -1; // 1. Use the socket() function to get a socket file descriptor int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (-1 == sockfd) { printf("socket open err."); return -1; } // 2. Bind local related information. If not, the system will randomly assign a port number struct sockaddr_in local_addr = {0}; local_addr.sin_family = AF_INET; //Use IPv4 address local_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); //Native IP address local_addr.sin_port = htons(12341); //port bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));//Bind socket to IP and port // 3. Send data to the specified ip and port, '192.168.0.107' represents the destination ip address and 8266 represents the destination port number struct sockaddr_in sock_addr = {0}; sock_addr.sin_family = AF_INET; // Set the address family to IPv4 sock_addr.sin_port = htons(8266); // Set the port number information of the address sock_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); //Set IP address char sendbuf[]={"hello world, I am a UDP socket."}; int cnt = 10; while(cnt--) { ret = sendto(sockfd, sendbuf, sizeof(sendbuf)-1, 0, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); //printf("ret = %d \n",ret); sleep(1); } // 4. Waiting to receive the data sent by the other party struct sockaddr_in recv_addr; socklen_t addrlen = sizeof(recv_addr); char recvbuf[1024] = {0}; while(1) { ret = recvfrom(sockfd, recvbuf, 1024, 0,(struct sockaddr*)&recv_addr,&addrlen); //1024 indicates the maximum number of bytes received this time printf("[recv from %s:%d]%s \n",inet_ntoa(*(struct in_addr*)&recv_addr.sin_addr.s_addr),ntohs(recv_addr.sin_port),recvbuf); } // 5. Close the socket close(sockfd); }
5, Send and receive data at the same time
Now we can realize such a function, that is, run the program, and then send out the string I entered, and at the same time, we can also receive data. I use multithreading to realize this program, but to facilitate reception, we print the IP address and port number at the beginning of the program. The implementation effect is as follows:
Implementation code:
Note: pthread is not the default library of Linux system, but POSIX thread library. It is used as a library in Linux, so - lpthread (or - ptthread) is added to explicitly link the library.
#include <stdio.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <unistd.h> #include <pthread.h> void *recv_thread(void *arg) { int socket_fd = *(int *)arg; struct sockaddr_in recv_addr; socklen_t addrlen = sizeof(recv_addr); char recvbuf[1024] = {0}; while(1) { recvfrom(socket_fd, recvbuf, 1024, 0,(struct sockaddr*)&recv_addr,&addrlen); //1024 indicates the maximum number of bytes received this time printf("[recv from %s:%d]%s \n",inet_ntoa(*(struct in_addr*)&recv_addr.sin_addr.s_addr),ntohs(recv_addr.sin_port),recvbuf); } } int main(void) { int ret = -1; pthread_t th = -1; // 1. Use the socket() function to get a socket file descriptor int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (-1 == sockfd) { printf("socket open err."); return -1; } // 2. Bind local related information. If not, the system will randomly assign a port number struct sockaddr_in local_addr = {0}; local_addr.sin_family = AF_INET; //Use IPv4 address local_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); //Native IP address local_addr.sin_port = htons(12341); //port bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));//Bind socket to IP and port // 3. Print the local ip address and port number printf("local ipaddr and port->192.168.0.107:12341\n"); // 4. Create a thread to receive data ret = pthread_create(&th, NULL, recv_thread, &sockfd); // 5. Wait for the input data and send it out until the input data is' quit','192.168.0.107 'represents the destination ip address and 8266 represents the destination port number struct sockaddr_in sock_addr = {0}; sock_addr.sin_family = AF_INET; // Set the address family to IPv4 sock_addr.sin_port = htons(8266); // Set the port number information of the address sock_addr.sin_addr.s_addr = inet_addr("192.168.0.107"); //Set IP address char sendbuf[1024]={"hello world, I am a UDP socket."}; int cnt = 10; while(cnt--) { printf("please input a string.input 'quit' to quit.\n"); scanf("%s",sendbuf); if(strcmp(sendbuf,"quit") == 0) break; sendto(sockfd, sendbuf, strlen(sendbuf), 0, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); } // 6. Close the socket close(sockfd); }