Unix Socket span docker and host
root@ubuntu:~/c++# ./u_server Listener on port /tmp/echo_socket Waiting for connections ... Welcome message sent successfully Adding to list of sockets as 0 Welcome message sent successfully Adding to list of sockets as 1 recv failed: Connection reset by peer recv failed: Connection reset by peer Welcome message sent successfully Adding to list of sockets as 0 Welcome message sent successfully Adding to list of sockets as 1 recv failed: Connection reset by peer recv failed: Connection reset by peer ^C
server
root@ubuntu:~/c++# cat u_server.c #include <stdio.h> #include <stdint.h> #include <string.h> //strlen #include <stdlib.h> #include <errno.h> #include <unistd.h> //close #include <sys/un.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/stat.h> #include <netinet/in.h> #include <sys/time.h> //FD_SET, FD_ISSET, FD_ZERO macros #include<pthread.h> //for threading , link with lpthread #include <fcntl.h> #define SOCK_PATH "/tmp/echo_socket" bool daemonize() { int res = fork(); if (res < 0) { perror("fork"); return false; } if (res != 0) _exit(0); // Now we're running as the daemon... res = setsid(); if (res < 0) { perror("setsid"); return false; } if (false) { int fd = open("/dev/null", O_RDWR, 0); if (fd >= 0) { dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); if (fd > 2) close(fd); } } return true; } /* * This will handle connection for each client * */ void *connection_handler(void *socket_desc) { //Get the socket descriptor int& sock = *(int*)socket_desc; int read_size; char client_message[2000]; //Send some messages to the client const char *message = "Greetings! I am your connection handler\n"; write(sock , message , strlen(message)); message = "Now type something and i shall repeat what you type \n"; write(sock , message , strlen(message)); //Receive a message from client while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 ) { //end of string marker client_message[read_size] = '\0'; printf("client sock %d and recv %s \n", sock, client_message); //Send the message back to client write(sock , client_message , strlen(client_message)); //clear the message buffer memset(client_message, 0, 2000); } if(read_size == 0) { puts("Client disconnected"); fflush(stdout); } else if(read_size == -1) { perror("recv failed"); } // sock = 0; return 0; } int main(int argc , char *argv[]) { bool dflag = false; if (dflag && !daemonize()) { return -1; } int master_socket; int client_socket[30]; int max_clients = 30; struct sockaddr_un address; //set of socket descriptors fd_set readfds; //initialize all client_socket[] to 0 so not checked memset(client_socket, 0, sizeof(client_socket)); //create a master socket if( (master_socket = socket(AF_UNIX , SOCK_STREAM , 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } unlink(SOCK_PATH); //type of socket created address.sun_family = AF_UNIX; strcpy(address.sun_path, SOCK_PATH); size_t len = strlen(address.sun_path) + sizeof(address.sun_family); if (bind(master_socket, (struct sockaddr *)&address, len)<0) { perror("bind failed"); exit(EXIT_FAILURE); } printf("Listener on port %s \n", SOCK_PATH); //try to specify maximum of 3 pending connections for the master socket if (listen(master_socket, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } //accept the incoming connection size_t addrlen = sizeof(address); puts("Waiting for connections ..."); while(true) { //clear the socket set FD_ZERO(&readfds); //add master socket to set FD_SET(master_socket, &readfds); int max_sd = master_socket; //add child sockets to set for (int i = 0 ; i < max_clients ; i++) { //socket descriptor int sd = client_socket[i]; //if valid socket descriptor then add to read list if(sd > 0) FD_SET( sd , &readfds); //highest file descriptor number, need it for the select function if(sd > max_sd) max_sd = sd; } //wait for an activity on one of the sockets , timeout is NULL , so wait indefinitely int activity = select( max_sd + 1 , &readfds , NULL , NULL , NULL); if ((activity < 0) && (errno != EINTR)) { printf("select error"); } //If something happened on the master socket , then its an incoming connection if (FD_ISSET(master_socket, &readfds)) { int new_socket = 0; if ((new_socket = accept(master_socket, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) { perror("accept"); exit(EXIT_FAILURE); } puts("Welcome message sent successfully"); //add new socket to array of sockets for (int i = 0; i < max_clients; i++) { //if position is empty if( client_socket[i] == 0 ) { client_socket[i] = new_socket; printf("Adding to list of sockets as %d\n" , i); pthread_t thread_id; if( pthread_create( &thread_id , NULL , connection_handler , (void*) &client_socket[i]) < 0) { perror("could not create thread"); return 1; } pthread_detach(thread_id); break; } } } } return 0; }
g++ -pthread u_server.c -o u_server
client
root@ubuntu:~/c++# cat u_client.c #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <stddef.h> #include <sys/socket.h> #include <sys/un.h> #include <errno.h> #include <string.h> #include <unistd.h> #define MAXLINE 80 char *client_path = "client.socket"; char *server_path = "/tmp/echo_socket"; int main(int argc, char* argv[]) { struct sockaddr_un cliun, serun; int len; char buf[100]; int sockfd, n; if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){ perror("client socket error"); exit(1); } // 一般显式调用bind函数,以便服务器区分不同客户端 memset(&cliun, 0, sizeof(cliun)); cliun.sun_family = AF_UNIX; strcpy(cliun.sun_path, argv[2]); len = offsetof(struct sockaddr_un, sun_path) + strlen(cliun.sun_path); unlink(cliun.sun_path); if (bind(sockfd, (struct sockaddr *)&cliun, len) < 0) { perror("bind error"); exit(1); } memset(&serun, 0, sizeof(serun)); serun.sun_family = AF_UNIX; strcpy(serun.sun_path, server_path); len = offsetof(struct sockaddr_un, sun_path) + strlen(serun.sun_path); if (connect(sockfd, (struct sockaddr *)&serun, len) < 0){ perror("connect error"); exit(1); } while(fgets(buf, MAXLINE, stdin) != NULL) { write(sockfd, buf, strlen(buf)); n = read(sockfd, buf, MAXLINE); if ( n < 0 ) { printf("the other side has been closed.\n"); }else { write(STDOUT_FILENO, buf, n); } } close(sockfd); return 0; }
启动两个client
root@ubuntu:~/c++# ./u_client /tmp/echo_socket uclient2 helloclient2 Greetings! I am your connection handler Now type something and i shall repeat wh at you type helloclient2 ^C
root@ubuntu:~/c++# ./u_client /tmp/echo_socket uclient3 helloclient3 Greetings! I am your connection handler Now type something and i shall repeat wh at you type helloclient3 ^C root@ubuntu:~/c++#
client 跑在容器中
root@ubuntu:~/c++# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cb37bad13c9e debian "bash" 4 seconds ago Up 3 seconds kind_bartik fa2d3b3aec76 busybox "sh" 6 months ago Up 6 months cranky_mendeleev a9ab3ca9fa95 busybox "sh" 6 months ago Up 6 months stoic_mcclintock root@ubuntu:~/c++# docker cp u_client cb37bad13c9e:/ root@ubuntu:~/c++#
root@ubuntu:~# docker run --runtime runc --rm -ti debian root@cb37bad13c9e:/# ls bin boot dev etc home lib media mnt opt proc root run sbin srv sys tmp u_client usr var root@cb37bad13c9e:/# ./u_client connect error: No such file or directory root@cb37bad13c9e:/# ls 'HOSTNAME=cb37bad13c9e' bin boot dev etc home lib media mnt opt proc root run sbin srv sys tmp u_client usr var root@cb37bad13c9e:/# chmod +x u_client root@cb37bad13c9e:/# ./u_client connect error: No such file or directory root@cb37bad13c9e:/#
root@ubuntu:~/c++# docker search gcc NAME DESCRIPTION STARS OFFICIAL AUTOMATED gcc The GNU Compiler Collection is a compiling s… 603 [OK] rikorose/gcc-cmake Build on top off the official gcc image incl… 26 [OK] arm32v7/gcc The GNU Compiler Collection is a compiling s… 7 arm64v8/gcc The GNU Compiler Collection is a compiling s… 6 randomdude/gcc-cross-x86_64-elf GCC built to target x86_64-elf. Shamelessly … 2 [OK] teeks99/gcc-ubuntu Versions of gcc running on ubuntu The goal … 1 [OK] conanio/gcc5 1 conanio/gcc7 1 unikraft/gcc 1 ppc64le/gcc The GNU Compiler Collection is a compiling s… 1 conanio/gcc8 1 trollin/gcc 0 rushmash/gcc-arm-embedded-docker gcc-arm-none-eabi toolchain 0 [OK] etews/gcc-cmake-python Gcc with cmake and python based on Debian 0 celiangarcia/gcc6-cmake Cmake built on top of official gcc 6 image. 0 conanio/gcc9-jnlp-slave 0 s390x/gcc The GNU Compiler Collection is a compiling s… 0 phanoix/gcconnex :latest image based off alpine 0 [OK] amd64/gcc The GNU Compiler Collection is a compiling s… 0 celiangarcia/gcc8-cmake Cmake built on top of official gcc 8 image. 0 vcatechnology/gcc5-armv7hf Specialization of conanio/gcc5-armv7hf 0 conanio/gcc9 0 arm32v5/gcc The GNU Compiler Collection is a compiling s… 0 celiangarcia/gcc7-cmake Cmake built on top of official gcc 7 image. 0 microblinkdev/gcc-devenv GCC-based development environment 0 root@ubuntu:~/c++#
root@ubuntu:~# docker run --runtime runc --rm -ti arm64v8/gcc Unable to find image 'arm64v8/gcc:latest' locally latest: Pulling from arm64v8/gcc d62e7e7f9965: Pulling fs layer 8ba77e956dd9: Pulling fs layer 02d06261b657: Pulling fs layer a74967d868a7: Waiting dbf0f9cf1993: Waiting
root@ubuntu:~# docker run --runtime runc --rm -ti gcc Unable to find image 'gcc:latest' locally latest: Pulling from library/gcc d62e7e7f9965: Pull complete 8ba77e956dd9: Pull complete 02d06261b657: Pull complete a74967d868a7: Pull complete dbf0f9cf1993: Pull complete 56e9a718d723: Pull complete 5cef519312bd: Pull complete fb215d03a23c: Pull complete 6465a55565b6: Pull complete Digest: sha256:3f8b39b5a9e8f03e1bb00ae166f9350fb0fe4413076a697fff9fd8355d13c0ea Status: Downloaded newer image for gcc:latest root@1010b7db727a:/# ls bin boot dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var root@1010b7db727a:/# gcc version /usr/bin/ld: cannot find version: No such file or directory collect2: error: ld returned 1 exit status root@1010b7db727a:/# gcc --version gcc (GCC) 11.1.0 Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. root@1010b7db727a:/# ls bin boot dev etc home lib media mnt opt proc root run sbin srv sys tmp u_client.c usr var root@1010b7db727a:/# gcc u_client.c -o u_client root@1010b7db727a:/# ./u_client connect error: No such file or directory root@1010b7db727a:/# exit exit
采用mount bind
root@ubuntu:~# docker run --runtime runc --mount type=bind,src=/tmp/echo_socket,dst=/tmp/echo_socket --rm -ti gcc root@bf56307e7da3:/# ls bin boot dev etc home lib media mnt opt proc root run sbin srv sys tmp u_client.c usr var root@bf56307e7da3:/# gcc u_client.c -o u_client
root@bf56307e7da3:/# ./u_client /tmp/echo_socket client.socket Greetings! I am your connection handler Now type something and i shall repeat wh at you type hello googd hello docker googd run in docker docker
server 端 in host