主頁 > 軟體設計 > 網路編程TCP/IP協議(二)----- 多行程多執行緒服務器

網路編程TCP/IP協議(二)----- 多行程多執行緒服務器

2021-08-13 07:16:49 軟體設計

1、前言

上一篇已經實作了服務器端與客戶端之間最基礎通信,但存在一些問題,最大的問題是上篇中一個服務器端只能連接一個客戶端,如何讓一個服務器端可以連接多個客戶端呢?利用多行程多執行緒實作,

2、優化說明

  • 優化1: 讓服務器程式可以系結在任何的IP地址上,
  • 優化2 :通程序式獲取剛建立的socket的客戶端的IP地址和埠號,
  • 優化3 :連接多個客戶端,
  • 優化4:允許系結地址快速重用,

3、幾個函式

在這里插入圖片描述

1、IP地址轉換函式
1、 本地位元組序轉化為網路位元組序

 #include <arpa/inet.h>
 int inet_pton(int af, const char *src, void *dst);

  • af:地址協議族(IPV4:4:AF_INET或IPV6::AF_INET6)
  • src:是一個指標,填寫點分形式的IP地址
  • dest:轉換的結果給dst
  • 在服務器端Bind()函式系結IP地址和埠號,客戶端connect()函式填充IP地址和埠號時,是將本地位元組序轉化為網路位元組序,
2、網路位元組序轉化為本地位元組序

 #include <arpa/inet.h>
 int inet_ntop(int af, const char *src, void *dst, socklen_t size);
  • af:引數同上
  • src:從結構體中讀取IP地址,該結構體中有IP地址和埠號等資訊,
  • dst:讀取到的IP地址保存的地址,如果是IPV4,結果為點分形式,
  • 結構體大小
  • 服務器端讀取客戶端IP地址和埠號時,需要將網路位元組序轉化為本地位元組序,
2、埠位元組序轉化
       #include <arpa/inet.h>

       uint32_t htonl(uint32_t hostlong);    //本地位元組序到網路位元組序 4位元組

       uint16_t htons(uint16_t hostshort);  //本地位元組序到網路位元組序 2位元組

       uint32_t ntohl(uint32_t netlong);   //網路位元組序到本地位元組序  4位元組

       uint16_t ntohs(uint16_t netshort); // 網路位元組序到本地位元組序 2位元組

3、行程創建函式
 #include <sys/types.h>
 #include <unistd.h>
  pid_t fork(void);
  • 創建一個新的行程,新行程為當前行程的子行程,fork()通過回傳值來判斷行程是在子行程中,還是父行程中,
  • 回傳值 = 0,在子行程中; 回傳值 <0,創建子行程失敗;回傳值 >0,在父行程,
  • 子行程繼承父行程的內容,子行程先結束時,父行程需要及時回收,

4、行程回收函式

 #include <sys/types.h>
 #include <sys/wait.h>
 pid_t waitpid(pid_t pid, int *wstatus, int options);

  • pid=-1 等待任何子行程,此時的waitpid()函式就退化成了普通的wait()函式,
  • wstatus指定用于保存子行程回傳值和結束方式的地址,
  • options 指定回收方式,0或WNOHANG,WNOHANG為非阻塞方式,
5、執行緒創建函式
 #include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);

  • 引數thread為指向執行緒識別符號的指標,
  • attr 為執行緒屬性,NULL表示默認,
  • start_routine 執行緒執行函式,
  • arg為傳遞給執行函式的引數,

多執行緒實作-服務器端

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <errno.h>   /*與error相關的*/
#include <arpa/inet.h>
#define  SERV_PORT 5001
#define  SERV_IP_ADDR "192.168.192.143"
#define  BACKLOG  5
#define  QUIT_STR "quit"

void  cli_data_handle(void * arg);
int main()
{
        int fd =-1;
        struct sockaddr_in sin;
        /*第一步:創建socket fd*/
        if( (fd = socket(AF_INET,SOCK_STREAM,0)) < 0){
                perror("socket");
                exit(1);
        }
                /*優化4:允許系結地址快速重用*/
        int b_reuse = 1;
        setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof(int));

        /*第二步:系結*/
        /*填充struct sockaddr_in結構體變數*/
        bzero(&sin,sizeof(sin)); //清空結構體
        sin.sin_family = AF_INET;//TCP/IP協議族
        sin.sin_port = htons(SERV_PORT); //轉化為網路位元組序埠號
        /*優化1:讓服務器程式可以系結在任何的IP地址上*/
#if 1
        sin.sin_addr.s_addr = htonl(INADDR_ANY);
#else
        if(inet_pton(AF_INET,SERV_IP_ADDR,&sin.sin_addr) != 1){//ip地址轉化為網路位元組序
                perror("inet_pton");
                exit(1);
        }
#endif
        /*系結,強制轉化為struct sockaddr結構體*/
        if(bind(fd,(struct sockaddr *)&sin,sizeof(sin)) < 0){
                perror("bind error");
                exit(1);
        }
        /*第三步:呼叫listen()把主動套接字變成被動套接字*/
        if(listen(fd,BACKLOG) < 0){ //BACKLOG 通常為 5
                perror("listen");
                exit(1);
        }
        /*第四步:阻塞等待客戶端連接請求*/
        printf("Server starting......OK\n");
        int newfd = -1;
#if 0
        newfd = accept(fd,NULL,NULL);//和客戶端連接成功時,回傳一個新的newfd
        if(newfd < 0){
                perror("accept");
                exit(1);
        }
#else
        /*優化2:通程序式獲取剛建立的socket的客戶端的IP地址和埠號*/
        pthread_t  tid;
        struct sockaddr_in cin; //用于存放客戶端的資訊
        socklen_t addrlen = sizeof(cin);
        while(1){
        if((newfd = accept(fd,(struct sockaddr*)&cin,&addrlen)) < 0){
                perror("accept");
                exit(1);
        }
        char ipv4_addr[16];/*字串陣列,用于存放轉化后的IP地址*/
        if(! inet_ntop(AF_INET,(void *)&cin.sin_addr,ipv4_addr,sizeof(cin))){
                perror("inet_ntop");
                exit(1);
        }
        printf("Client(%s:%d) is connected!\n",ipv4_addr,ntohs(cin.sin_port));
        pthread_create(&tid,NULL,(void *)cli_data_handle,(void*)&newfd);//創建執行緒,傳入函式的引數為newfd
        }

        close(fd);
}
#endif
void  cli_data_handle(void * arg){

        int newfd = *(int*)arg;  //先強制轉換為int型指標,再取值
        printf("handler thread:newfd = %d\n",newfd);/**/

        int ret = -1;
        char buf[BUFSIZ];
        while(1){
                bzero(buf,BUFSIZ);
                do{
                ret  = read(newfd,buf,BUFSIZ-1);//讀取客戶端寫入到BUF中的資料
                }while(ret < 0 && EINTR == errno);
                if(ret < 0){  // 出錯
                        perror("read");
                        exit(1);
                }
                if(!ret){ //沒有讀到資料時,退出當前回圈
                        break;
                }
                printf("Receive data(client fd:%d):%s\n",newfd,buf);
                if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR))){//相等時 回傳0
                     printf("Client(fd = %d) is exiting!\n",newfd);  //該比較函式忽略字母大小寫
                      break;
                }
     }
        close(newfd);/*退出回圈后,關閉*/

}

多行程實作 服務器端

  1 #include <stdio.h>
  2 #include <pthread.h>
  3 #include <string.h>
  4 #include <unistd.h>
  5 #include <stdlib.h>
  6 #include <string.h>
  7 #include <unistd.h>
  8 #include <stdlib.h>
  9 #include <sys/types.h>
 10 #include <sys/wait.h>
 11 #include <sys/socket.h>
 12 #include <strings.h>
 13 #include <netinet/in.h>
 14 #include <netinet/ip.h> /* superset of previous */
 15 #include <signal.h>
 16 #include <errno.h>   /*與error相關的*/
 17 #include <arpa/inet.h>
 18 #define  SERV_PORT 5001
 19 #define  SERV_IP_ADDR "192.168.192.143"
 20 #define  BACKLOG  5
 21 #define  QUIT_STR "quit"
 22
 23 void  cli_data_handle(void * arg);
 24         /*回收子行程*/
 25 void sig_child_handle(int signo){
 26         if(SIGCHLD == signo){ //子行程暫停或終止時產生,父行程將收到
 27         waitpid(-1, NULL, WNOHANG);
 28         }
 29
 30 }
 31 int main()
 32 {
 33         int fd =-1;
 34         struct sockaddr_in sin;
 35
 36         signal(SIGCHLD,sig_child_handle);
 37
 38         /*第一步:創建socket fd*/
 39         if( (fd = socket(AF_INET,SOCK_STREAM,0)) < 0){
 40                 perror("socket");
 41                 exit(1);
 42         }
 43         /*優化4:允許系結地址快速重用*/
 44         int b_reuse = 1;
 45         setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof(int));
 46         /*第二步:系結*/
 47         /*填充struct sockaddr_in結構體變數*/
 48         bzero(&sin,sizeof(sin)); //清空結構體
 49         sin.sin_family = AF_INET;//TCP/IP協議族
 50         sin.sin_port = htons(SERV_PORT); //轉化為網路位元組序埠號
 51         /*優化1:讓服務器程式可以系結在任何的IP地址上*/
 52 #if 1
 53         sin.sin_addr.s_addr = htonl(INADDR_ANY);
 54 #else
 55         if(inet_pton(AF_INET,SERV_IP_ADDR,&sin.sin_addr) != 1){//ip地址轉化為網路位元組序
 56                 perror("inet_pton");
 57                 exit(1);
 58         }
 59 #endif
 60         /*系結,強制轉化為struct sockaddr結構體*/
 61         if(bind(fd,(struct sockaddr *)&sin,sizeof(sin)) < 0){
 62                 perror("bind error");
 63                 exit(1);
 64         }
 65         /*第三步:呼叫listen()把主動套接字變成被動套接字*/
 66         if(listen(fd,BACKLOG) < 0){ //BACKLOG 通常為 5
 67                 perror("listen");
 68                 exit(1);
 69         }
 70         /*第四步:阻塞等待客戶端連接請求*/
 71         printf("Server starting......OK\n");
 72         int newfd = -1;
 73 #if 0
 74         newfd = accept(fd,NULL,NULL);//和客戶端連接成功時,回傳一個新的newfd
 75         if(newfd < 0){
 76                 perror("accept");
 77                 exit(1);
 78         }
 79 #else
 80         /*優化2:通程序式獲取剛建立的socket的客戶端的IP地址和埠號*/
 81
 82         //pthread_t  tid;
 83         struct sockaddr_in cin;
 84         socklen_t addrlen = sizeof(cin);
 85         while(1){
 86         pid_t pid = -1;
 87         if((newfd = accept(fd,(struct sockaddr*)&cin,&addrlen)) < 0){
 88                 perror("accept");
 89                 exit(1);
 90         }
 91
 92         if((pid = fork()) < 0){
 93                 perror("fork");
 94                 break;
 95         }
 96         if( 0 == pid)//子行程
 97         {
 98
 99         close(fd);//不用fd
100         char ipv4_addr[16];/*字串陣列,用于存放轉化后的IP地址*/
101         if(! inet_ntop(AF_INET,(void *)&cin.sin_addr,ipv4_addr,sizeof(cin))){
102                 perror("inet_ntop");//從網路位元組序轉化為本地位元組序
103                 exit(1);
104              }   
105         printf("Client(%s:%d) is connected!\n",ipv4_addr,ntohs(cin.sin_port));
106         cli_data_handle(&newfd);
107         return 0;
108         }
109         else{   //pid > 0,父行程
110           close(newfd);
111         }
112
113         }
114 }
115 #endif
116 void  cli_data_handle(void * arg){
117
118         int newfd = *(int*)arg;  //先強制轉換為int型指標,再取值
119         printf("child handling process:newfd = %d\n",newfd);/**/
120         int ret = -1;
121         char buf[BUFSIZ];
122         while(1){
123                 bzero(buf,BUFSIZ);
124                 do{
125                 ret  = read(newfd,buf,BUFSIZ-1);//讀取客戶端寫入到BUF中的資料
126                 }while(ret < 0 && EINTR == errno);
127                 if(ret < 0){  // 出錯
128                         perror("read");
129                         exit(1);
130                 }
131                 if(!ret){ //沒有讀到資料時,退出當前回圈
132                         break;
133                 }
134                 printf("Receive data(client fd:%d):%s\n",newfd,buf);
135                 if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR))){//相等時 回傳0
136                      printf("Client(fd = %d) is exiting!\n",newfd);  //該比較函式忽略字母大小寫
137                       break;
138                 }
139      }
140      close(newfd);
141 }
142
143
~
~
~


客戶端 執行時輸入 ./client serv_ip serv_port

/*./client serv_ip serv_port*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <errno.h>   /*與error相關的*/
#include <arpa/inet.h>
#define  SERV_PORT 5001
#define  SERV_IP_ADDR "192.168.192.143"
#define  BACKLOG  5
#define  QUIT_STR "quit"
void usage(char *s)
{
        printf("\n%s serv_ip serv_port",s);
        printf("\n\t serv_ip:server ip address");
        printf("\n\t serv_port:server port(>5000)\n\n");
}
int main(int argc,char *argv[])
{
        int fd = -1;
        int port = -1;
        if(argc != 3){
                usage(argv[0]);
                exit(1);
}
        struct sockaddr_in sin;
        /*第一步:創建socket fd*/
        if( (fd = socket(AF_INET,SOCK_STREAM,0)) < 0){
                perror("socket");
                exit(1);
        }
        port  = atoi(argv[2]);  //輸入的第三個引數 埠號
        if(port < 5000){
                usage(argv[0]);
                exit(1);
        }
        /*第二步:連接*/
        /*填充struct sockaddr_in結構體變數*/
        bzero(&sin,sizeof(sin)); //清空結構體
        sin.sin_family = AF_INET;//TCP/IP協議族
        sin.sin_port = htons(port); //轉化為網路位元組序
        if(inet_pton(AF_INET,argv[1],(void*)&sin.sin_addr) != 1){//ip地址轉化為網路位元組序
                perror("inet_pton");
                exit(1);
        }
        if(connect(fd,(struct sockaddr *)&sin,sizeof(sin)) < 0){
                perror("connect ");
                exit(1);
        }
        /*寫入資料*/
        char buf[BUFSIZ];
        while(1){
        bzero(buf,BUFSIZ);
        if(fgets(buf,BUFSIZ-1,stdin) ==  NULL){  //鍵盤輸入資料到buf
                continue;
        }
        write(fd,buf,strlen(buf));
        if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR))){//相等時 回傳0
                        printf("Client is exiting!\n");  //該比較函式忽略字母大小寫
                        break;
        }
 }

/*關閉*/
        close(fd);
}

4、編譯運行

/*多行程實作 服務器端*/
book@100ask:~/socket$ ./server3
Server starting......OK
Client(192.168.192.143:36066) is connected!    //行程1
child handling process:newfd = 4
Receive data(client fd:4):welcome
Receive data(client fd:4):147
Receive data(client fd:4):Next change client

Client(192.168.192.143:36068) is connected! //行程2
child handling process:newfd = 4
Receive data(client fd:4):hello
Receive data(client fd:4):2021
Receive data(client fd:4):456
Receive data(client fd:4):quit
Client(fd = 4) is exiting!

Client(192.168.192.143:36070) is connected!//行程3
child handling process:newfd = 4
Receive data(client fd:4):11111
Receive data(client fd:4):22222
Receive data(client fd:4):quit

 /*多行程實作 客戶端*/
book@100ask:~/socket$ ./client 192.168.192.143 5001  //輸入的三個引數,client 1
welcome
147
Next change client
book@100ask:~/socket$ ./client 192.168.192.143 5001 //client 2
hello
2021
456
quit
Client is exiting!
book@100ask:~/socket$ ./client 192.168.192.143 5001//client 3
11111
22222
quit
Client is exiting!
/*多執行緒實作-服務器端*/
Client(192.168.192.143:36076) is connected!    //執行緒1
handler thread:newfd = 4
Receive data(client fd:4):qwe
Receive data(client fd:4):789

Client(192.168.192.143:36078) is connected!  //執行緒2
handler thread:newfd = 5
Receive data(client fd:5):000
Receive data(client fd:5):999

Client(192.168.192.143:36080) is connected!  //執行緒3
handler thread:newfd = 6
Receive data(client fd:6):abc
Receive data(client fd:6):711
/*多執行緒實作-客戶端*/
book@100ask:~/socket$ ./client 192.168.192.143 5001 //client 1
qwe
789
book@100ask:~/socket$ ./client 192.168.192.143 5001//client 2
000
999
book@100ask:~/socket$ ./client 192.168.192.143 5001//client 3
abc
711


轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/293324.html

標籤:其他

上一篇:系統學習nginx(第三天)nginx作為下載器使用

下一篇:docker鏡像和容器的匯入匯出

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more