openwrt development summary using pthread to realize socket multi process server

At the beginning of last year, there were a lot of code written in openwrt, although I felt sorry that there was a lot of code written in openwrt in the early days of the company.

Let's briefly introduce the socket multi process server on openwrt.

Look at the code

This is c language code. The code written at that time was not very good. Don't spray it. It should be noted that some Linux libraries are used here. They cannot be compiled directly on Windows. They can be compiled on the subsystem on Windows. If necessary, please see my previous blog.

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <signal.h>
#include <pthread.h>
 
#define IP	"192.168.121.1"
#define PORT  2050
#define QUEUE   10
#define BUFFER_SIZE 8196

//receive data 
void *recv_data(int conn_fd);

//Get string file parameters
char* get_args();
 
int main()
{
	
	printf("This is 17:31");
		
	//Manually capture the pipeline rupture signal and ignore it
	signal(SIGPIPE, SIG_IGN);
	
    ///Define sockfd
    int server_sockfd = socket(AF_INET,SOCK_STREAM, 0);
	int conn;
 
    ///Define sockaddr_in
    struct sockaddr_in server_sockaddr;
    server_sockaddr.sin_family = AF_INET;//IPv4
    server_sockaddr.sin_port = htons(PORT);
    server_sockaddr.sin_addr.s_addr = inet_addr(IP);//You need to set the top IP, or you can't connect it
	bzero(&(server_sockaddr.sin_zero),8);//Fill the rest of the structure
 
    ///bind, 0 for success and - 1 for error
    if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1)
    {
        perror("bind");
        exit(1);
    }
	
	printf("bind success, start listen!");
 
    ///listen, 0 is returned for success, and - 1 is returned for error
    if(listen(server_sockfd,QUEUE) == -1)
    {
        perror("listen");
        exit(1);
    }
	
	while(1)
    {
        pthread_t thread;
		
		///Client socket
		struct sockaddr_in client_addr;
		socklen_t length = sizeof(client_addr);
 
        if (-1 == (conn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length)))
        {
            perror("accept");
            continue;
        }
 
        if (0!= pthread_create(&thread, NULL, recv_data, conn))
        {
            perror("pthread_create");
            break;
        }
    }
 
    shutdown(server_sockfd,2);
    shutdown(conn,2);
    return 0;

}


void *recv_data(int conn_fd)
{
    int  recv_len;
    char recv_buf[BUFFER_SIZE];
 
    for(;;)
    {
		bzero(recv_buf, sizeof(recv_buf));
        recv_len = recv(conn_fd,recv_buf,BUFFER_SIZE,0);
 
        if(-1==recv_len)
        {
            perror("recv");
            exit(1);
        }
        
		recv_buf[recv_len] = '\0';
 
        if(strncmp(recv_buf,"exit",4)==0)
        {
            printf("%s\n",recv_buf);
            break;
        }
		
		 
        printf("Receive data:%s\n", recv_buf);
		
		if(send(conn_fd, get_args(), strlen(get_args()), 0) == -1)
		{
			perror("send");
            exit(1);
		}
		
    }
 
    close(conn_fd);
    pthread_exit(NULL);
}

char* get_args()
{
	//char data[8196];
	//char *data = malloc(8196);
	char *data = (char*)calloc(BUFFER_SIZE, sizeof(char));//With initialization
	char tmp[8] = { 0 };
    FILE* pFile = fopen("/etc/config/site-manager", "r");
    while ( fread(tmp, sizeof(char), 2, pFile) )
    {
        strcat(data,tmp);
		bzero(tmp,sizeof(tmp));
        //memset(tmp,0,sizeof(tmp));
    }
    fclose(pFile);
	return data;
}

pthread is used here for multithreading. The data is the uci parameter obtained from / etc/config /. You can talk about the uci parameter later. This can be modified from the web page and supports two-way binding.

UDP server is used here, which can also be written as TCP. They are similar and can be studied by ourselves.

    int server_sockfd = socket(AF_INET,SOCK_STREAM, 0);

Other notes are very clear. At that time, the attitude of just graduated was still very correct. It is worth noting that there was a problem of pipeline rupture. If the socket client directly hung up the socket connection without the knowledge of the server, it will lead to the connection from the server to the client and the disconnection from the client to the server. At this time, once the server application sends data to the client, There will be an error of pipeline rupture, resulting in the server program being closed. Anyway, let you add the following sentence

	//Manually capture the pipeline rupture signal and ignore it
	signal(SIGPIPE, SIG_IGN);

Write configuration file

Due to the introduction of pthread library, our configuration file needs to be modified.

  • Source directory Makefile
argserver : argserver.o
	$(CC) $(LDFLAGS) argserver.o -o argserver -lpthread

argserver.o : argserver.c
	$(CC) $(CFLAGS) -c argserver.c

clean :
	rm *.o argserver

Here, - lpthread needs to be added during compilation, indicating that the library is added to participate in compilation.

  • Outer Makefile
include $(TOPDIR)/rules.mk

PKG_NAME:=argserver
PKG_RELEASE:=1.0
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
TARGET_LDFLAGS:= -lpthread

include $(INCLUDE_DIR)/package.mk

define Package/argserver
	SECTION:=utils
	CATEGORY:=Utilities
	TITLE:=argserver -- socket server to get arg info
	DEPENDS:=+libpthread
endef

define Package/argserver/description
	socket server to get arg info .
endef

define Build/Prepare
	echo "Here is Package/Prepare"
	mkdir -p $(PKG_BUILD_DIR)
	$(CP) ./src/* $(PKG_BUILD_DIR)/
endef

define Package/argserver/install
	echo "Here is Package/install"
	$(INSTALL_DIR) $(1)/bin $(1)/etc/init.d/
	$(INSTALL_BIN) $(PKG_BUILD_DIR)/argserver $(1)/bin/
	$(INSTALL_BIN) ./auto/argserver $(1)/etc/init.d/
endef

$(eval $(call BuildPackage,argserver))

Note two modifications. The following indicates the addition of dependent libraries. The one above is involved in compilation.

Support pthread

Generally speaking, openwrt should add pthread library by default. If you are not sure, you can find it in the menu

make menuconfig

Use "/" in the menu to search pthread to see if it is checked. If it is checked, our program can run normally. If you can't compile firmware with openwrt, it depends on whether the firmware you use supports pthread. Generally speaking, it does.

test

Just find a udp testing tool on the Internet, like TCPUDPDbg. The next one on the Internet is very simple to use, so I won't write it. I also recommend a multifunctional tool IPOP, which works well. I heard it was developed by Huawei. Just search it.

epilogue

What self starting function depends on my last blog.

end
Perfect flower scattering

Keywords: socket multiple processes udp openwrt pthread

Added by breath18 on Thu, 17 Feb 2022 14:27:35 +0200