C language network programming - UDP communication (this article is written in detail, and it also talks about how to use the network debugging assistant)

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);
  1. 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;
  2. 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;
  3. 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);
}


Willliam_william

Added by Nicksta on Tue, 11 Jan 2022 00:43:17 +0200