主頁 > 軟體設計 > 做TCP警告意味著資料包被忽略,"Wireshark(Warning/Malformed):Shortsegment.Segment/fragmentdoesnotcontainafullT

做TCP警告意味著資料包被忽略,"Wireshark(Warning/Malformed):Shortsegment.Segment/fragmentdoesnotcontainafullT

2021-12-30 22:41:08 軟體設計

我正在模擬 TCP,例如任何接收到的 tcp 資料包,所以應該有一個回應,為此我用 C 撰寫了我的服務器程式并創建了 TUN 介面,以便客戶端資料包讀取我的代碼,我的代碼的問題只是我得到SYN資料包,我用SYN ACK資料包回應它序列號和埠正確。在wireshark中,我看到我的SYN ACK回應,但我的客戶端不斷發送SYN資料包,并在中間路由器請求訊息中,在wireshark中它說

Expert Info (Warning/Malformed): Short segment. Segment/fragment does not contain a full TCP header (might be NMAP or someone else deliberately sending unusual packets)

這意味著什么,我很確定我將所有有效欄位都包含為值,但是為什么我不斷收到此警告,而我的客戶端似乎忽略了我的 SYN ACK 資料包。任何人都可以看看這個代碼

這是我的主要功能

int main(int argc, char **argv)
{
    const char *tun_ip = NULL;    /*virtual*/
    const char *remote_ip = NULL; /*physical*/
    ip4_addr_t local_ip4 = 0L;
    pthread_t tid_recv;//, tid_trans;
        void *thread_ret = NULL;
        

    _progname = argv[0];
    if (argc != 3) 
    {
        usage();
        exit(EXIT_FAILURE);
    }

    tun_ip = argv[1];
    remote_ip = argv[2];
       if (0 >= inet_pton(AF_INET, tun_ip, &local_ip4)) 
       {
        debug("%s: invalid IP address %s\n", _progname, tun_ip);
        exit(EXIT_FAILURE);
        }
    
    set_signal(SIGINT,  sigexit);
    set_signal(SIGQUIT, sigexit);

    
    _tun_fd = open_tun_iface(local_ip4);
    if (_tun_fd < 0 ) 
    {
        exit(EXIT_FAILURE);
    }
     


    _udp_fd = open_udp_socket();
    if (_udp_fd < 0 ) 
    {
        exit(EXIT_FAILURE);
    }
    
    
    if (0 >= inet_pton(AF_INET, remote_ip, &_remote_ip)) 
    {
        debug("%s: invalid IP address %s\n", _progname, remote_ip);
        exit(EXIT_FAILURE);
    }
    
    pthread_create(&tid_recv,  NULL, receiver,    NULL);
    
     while (!_do_exit)
        sleep(1);

    debug("** Shutting down...\n");
    close_tun_iface();
    shutdown(_udp_fd, 2); _udp_fd = -1;
    pthread_join(tid_recv,  &thread_ret);

    return 0;
}

這是我的接收者和回應者 TCP 執行緒

void * receiver(void *data)
{

    //struct sockaddr_in cliaddr = {0};
    int recvlen = -1;
    int writelen = -1;
    //socklen_t clilen = sizeof(cliaddr);

    while (!_do_exit)
    {
        //recvlen = rrecvfrom(_udp_fd, buf, sizeof(buf), 0, (struct sockaddr*)&cliaddr, &clilen);
        char buf[VPN_MAX_MTU] = {0};
        char buf_1[VPN_MAX_MTU] = {0};
        memset(buf,0,VPN_MAX_MTU);
        memset(buf_1,0,VPN_MAX_MTU);
        memset(buf,0,VPN_MAX_MTU);
        memset(buf_1,0,VPN_MAX_MTU);
        

        char *str_source=malloc(18);
        char *str_dest=malloc(18);
        memset(str_source,0,18);
        memset(str_dest,0,18);
        recvlen=read(_tun_fd,buf,VPN_MAX_MTU);
        if(recvlen>0)
        {

    //BUFFER received here        
        struct iphdr *iph=(struct iphdr *)buf;  
        struct iphdr *ip=(struct iphdr *)buf_1;
        int y=0;
        for(int b=0;b<(sizeof(struct iphdr) sizeof(struct tcphdr));b  )
        {
            if(y==20)
            {
                y=0;
                //printf("\n");
            }
            
            //printf("%x ",buf[b]<<24);
            
            
            y  ;
        
        }
    //      tcph->check=(tcp_chksum(iph,tcph));
        //iph->check = csum(iph, sizeof(*iph));
        char str_src[18]={0};
        char str_dest_t[18]={0};
           
           
        //printf("IN %s %s\n",get_ip_str_1(iph->saddr,str_src),get_ip_str_1(iph->daddr,str_dest_t));
        memcpy(&ip->daddr,&iph->saddr,sizeof(uint32_t));
        memcpy(&ip->saddr,&iph->daddr,sizeof(uint32_t));
        //printf("OUT %s %s\n",get_ip_str_1(ip->saddr,str_src),get_ip_str_1(ip->daddr,str_dest_t));
        //Create ip
        
        //DOUBLE CHECK FOR BYTE ORDER
        
        //ip->tot_len=iph->tot_len;
        populate_ip_some(iph,ip);
        ip->tos=0;
        ip->tos=iph->tos;
        ip->ihl         = 5;
        ip->version     = 4;
        ip->tot_len     = sizeof(struct iphdr)   sizeof(struct tcphdr);
        ip->protocol    = 6;
        ip->check=0; 
        //DOUBLE CHECK FOR BYTE ORDER
            ip->check = csum(ip, sizeof(*ip));
        ip->id=htons(100);

        //printf("before %d \n",htons(iph->check));
        iph->check=0; 
        //printf("middle %d\n",iph->check);
        //DOUBLE CHECK FOR BYTE ORDER
            iph->check = csum(iph, sizeof(*iph));

        int i=iph->ihl*4;
        struct tcphdr *tcph=(struct tcphdr *)(buf i);
        //printf("tcp before %x\n",htons(tcph->check));
        tcph->check=0;
        printf("TCP START\n");
        tcph->check=(tcp_chksum(iph,tcph));
            printf("TCP END\n");
        //printf("tcp after %d\n",(tcph->check));
        //printf("i == %d\n",i);
        //POSSIBLY PRINT IPH for fun
        //for(int a=0;a<recvlen;a  )
            //printf("%x\n",buf[a]);
        //GET ihl SEND --  tcp
        int j=(ip->ihl*4);
        //printf("j == %d\n",j);
        int x=0;
        
        //SEEK filling
        struct tcphdr *tcp=(struct tcphdr *)(buf_1 20);
        populate_tcp_some(tcph,tcp);//Do LOOK AT THIS FUNCTION TO [SEE/CORRECT IT] >:)
        if(tcph->syn==1)
        {
               printf("syn\n");
               populate_tcp_some(tcph,tcp);
               tcp->seq=htons(1);
               tcp->ack_seq=1;
               tcp->syn=1;
               tcp->ack=1;

               tcp->source=htons(80);
    //         printf("received tcp syn = %d\n",tcph->syn);
        }
        else
        {
               populate_tcp_some(tcph,tcp);
               tcp->syn=0;
               tcp->ack=1;
    //         printf("sending tcp syn = %d ack = %d\n",tcp->syn,tcp->ack);
           
        }
        populate_tcp_some(tcph,tcp);
        tcp->dest=tcph->source;
        //printf("%d %d SOURCE PORT \n",ntohs(tcph->source),ntohs(tcp->dest));
        
        tcp->source=htons(80);
        printf("%d %d PORTS \n",ntohs(tcp->source),ntohs(tcp->dest));
        tcp->check=0;
        //TCP CHECKSUM ABOUT TRIPPLE WOW
        tcp->check=tcp_chksum(ip,tcp);
        
        //printf("tcpH = %d |  tcp = %d\n",tcph->check,htons(tcp->check));
        //IF needed make payload data
        //WRITE
        if (recvlen > 0) 
        {
            writelen = write(_tun_fd, buf_1, sizeof(struct iphdr) sizeof(struct tcphdr));
            //debug("SR:d\n", recvlen);
            //debug("TW:d\n", writelen);
            
            if (writelen < 0) 
            {
            //debug("%s: rwrite() %s [%d]\n", _progname, strerror(errno), errno);
               //break;//NO NEED
            }
        }
        else if (recvlen < 0) 
        {
            //debug("%s: rrecvfrom() %s\n", _progname, strerror(errno));
               //break;//NO NEED
        }
        else if (recvlen == 0) 
        {
            //why
        }
    //FINALLY THEN SEND || DO WIRE SHARK 
        }
        
        // ...:)__ :) __:) ___:)___ (: __(:__ (;...  

    }

    debug("** Receiver ending.\n");
    pthread_exit(NULL);
}

這就是我設定 tun 界面的方式

int open_tun_iface(ip4_addr_t local_ip4)
{
    struct ifreq ifr_tun;
    int fd = -1;
    sock = -1;
  //  int mtu = VPN_PATH_MTU;

    if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
        debug("%s: Cannot open /dev/net/tun: %s. Do modprobe tun; lsmod\n", _progname, strerror(errno));
        return -1;
    }

    memset( &ifr_tun, 0, sizeof(ifr_tun) );
    ifr_tun.ifr_flags = IFF_TUN | IFF_NO_PI;// | IFF_NO_PI;
    if ((ioctl(fd, TUNSETIFF, (void *)&ifr_tun)) < 0) {
        debug("%s: TUNSETIFF error: %s\n", _progname, strerror(errno));
        close(fd);
        return -1;
    }

#if 0
    if (ioctl(fd, TUNSETPERSIST, 1) < 0) {
        debug("%s: TUNSETPERSIST error: %s\n", _progname, strerror(errno));
        close(fd);
        return -1;
    }
#endif

 sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
            printf("interface socket error\n");
        debug("%s: Cannot open udp socket: %s\n", _progname, strerror(errno) );
        close(fd);
        return -1;
    }

    if (set_ip(&ifr_tun, sock, local_ip4) < 0) {
        close(fd);
        close(sock);
        return -1;
    }


    if (ioctl(sock, SIOCGIFFLAGS, &ifr_tun) < 0) {
        debug("%s: SIOCGIFFLAGS: %s\n", _progname, strerror(errno));
        printf("SIOCSIFFLAGS\n");
        close(fd);
        close(sock);
        
        return -1;
    }

    ifr_tun.ifr_flags |= IFF_UP;
    ifr_tun.ifr_flags |= IFF_RUNNING;

    if (ioctl(sock, SIOCSIFFLAGS, &ifr_tun) < 0)  {
        debug("%s: SIOCSIFFLAGS: %s\n", _progname, strerror(errno));
        printf("SIOCSIFFLAGS\n");
        exit(0);    
        close(fd);
        close(sock);
        return -1;
    }


    /*mtu = get_if_mtu("eth0", sock);*/
  /*  mtu = path_mtu_to_ip(_remote_ip, 32);
    if (mtu <= 0) {
        mtu = INTERNET_MTU;
    }

    if (mtu   VPN_OVERHEAD > VPN_MIN_MTU)
        mtu -= VPN_OVERHEAD;

    if (0 != set_mtu(&ifr_tun, sock, mtu)) {
        close(fd);
        close(sock);
        return -1;
    }
*/
    debug("** TUN opened: %s\n", ifr_tun.ifr_name);
    //close(sock);
    
    return fd;
}

這是我的校驗和計算

通用 csum 函式

uint16_t csum(const void *data, const int length)
{
    uint16_t *accumalator = (uint16_t *)data;
    uint64_t sum = 0;

    /* Take care of the first 16-bit even blocks */
    for (int i = 0; i < length/2;   i) {
        sum  = *(accumalator i);

        if (sum >= 0x10000) {
            sum -= 0xffff;
        }
    }

    /* Handle the ending partial block */
    if (length % 2 != 0) {
        accumalator = accumalator  length/2; /* Point accumalator to the end block */
        uint16_t end_block = 0;
        memcpy(&end_block, accumalator, sizeof(length));
        sum  = ntohs(end_block);
        if (sum >= 0x10000) {
            sum -= 0xffff;
        }
    }
  
    return htons(~sum);
}

這是我計算和處理 TCP 校驗和計算

uint16_t tcp_chksum(struct iphdr *snd_iph, struct tcphdr *snd_tcph)
{
    struct psuedo_header psh;

    psh.src_addr = snd_iph->saddr;
    psh.dst_addr = snd_iph->daddr;
    psh.rsvd = 0;
    psh.proto = IPPROTO_TCP;
    psh.len_tcp = htons(sizeof(struct tcphdr)); /* No options, and no data */

    int pseudogram_size = sizeof(struct tcphdr)   sizeof(struct psuedo_header);
    //int pseudogram_size = sizeof(*snd_tcph)   sizeof(psh);
    char *pseudogram = malloc(pseudogram_size);

    memcpy(pseudogram, (char *)&psh, sizeof(struct psuedo_header));
    memcpy(pseudogram   sizeof(struct psuedo_header), snd_tcph, sizeof(struct tcphdr));

    return((csum1(pseudogram, pseudogram_size)));
    //return (htons(csum(snd_tcph, sizeof(struct my_tcph))   csum(&psh, sizeof(struct psuedo_header))));
}

int populate_ip_some(struct iphdr *o1,struct iphdr *o2) { o2->ihl=o1->ihl; //o2->version=o1->version; o2->id=htons(ntohs(o1->id) 1); o2->frag_off=o1->frag_off; o2->ttl=o1->ttl;o2->tos=0; //o2->協議=o1->協議;//o2->檢查=0;回傳 1;

}

int populate_tcp_flags(struct tcphdr *o1,struct tcphdr *o2) {

if(o1->syn==1 && o1->ack==0)
{

    printf("syn received\n\n");
    o2->syn=1;
    o2->ack=1;
    o2->rst=0;
    o2->fin=0;
    return 1;
}
if(o1->syn ==0 && o1->ack==1)
{
    printf("ack received\n\n");
    o2->syn=0;
    o2->ack=0;
    o2->rst=0;
    o2->fin=0;
    return 1;
}
if(o1->syn==0 && o1->fin==1)
{
    printf("fin received\n\n");
    o2->syn=0;
    o2->ack=1;
    o2->fin=0;
    o2->rst=0;
    return 1;
}

return 1;

}

uint32_t *ik;
int x=0;
int populate_tcp_some(struct tcphdr *o1,struct tcphdr *o2)
{
    if(x==0)
    {
        ik=malloc(sizeof(int)*100);
        if(ik==NULL)
        {printf("heap\n");exit(0);}
    }
    *(ik x)=x;
    o2->seq=htons(*(ik x));
    uint32_t host=ntohs(o1->seq);
    if(o1->syn==1)
    o2->ack_seq=1;
    else
    {
        //DOUBLE CHECK FOR TCP. ACK_SEQ SHOULD HAVE BEEN sizeof(OF TOTAL PACKET)   1
        //DOUBLE CHECK MAY NEED TO PASS IPHDR ipH   
        o2->ack_seq=(htons(host 1));
    }   
    o2->doff=o1->doff;
    o2->res1=o1->res1;
    o2->window=o1->window;
    o2->check=0;
    o2->urg_ptr=o1->urg_ptr;
    x  ;
    return 1;
}

這是我的 netinet/ip.h,它有 iphdr 定義

struct iphdr
  {
#if __BYTE_ORDER == __LITTLE_ENDIAN
    unsigned int ihl:4;
    unsigned int version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
    unsigned int version:4;
    unsigned int ihl:4;
#else
# error "Please fix <bits/endian.h>"
#endif
    uint8_t tos;
    uint16_t tot_len;
    uint16_t id;
    uint16_t frag_off;
    uint8_t ttl;
    uint8_t protocol;
    uint16_t check;
    uint32_t saddr;
    uint32_t daddr;
    /*The options start here. */
  };

這是 netinet/tcp.h 可以找到我的 tcphdr 結構

struct tcphdr
  {
    __extension__ union
    {
      struct
      {
    uint16_t th_sport;  /* source port */
    uint16_t th_dport;  /* destination port */
    tcp_seq th_seq;     /* sequence number */
    tcp_seq th_ack;     /* acknowledgement number */
# if __BYTE_ORDER == __LITTLE_ENDIAN
    uint8_t th_x2:4;    /* (unused) */
    uint8_t th_off:4;   /* data offset */
# endif
# if __BYTE_ORDER == __BIG_ENDIAN
    uint8_t th_off:4;   /* data offset */
    uint8_t th_x2:4;    /* (unused) */
# endif
    uint8_t th_flags;
# define TH_FIN 0x01
# define TH_SYN 0x02
# define TH_RST 0x04
# define TH_PUSH    0x08
# define TH_ACK 0x10
# define TH_URG 0x20
    uint16_t th_win;    /* window */
    uint16_t th_sum;    /* checksum */
    uint16_t th_urp;    /* urgent pointer */
      };
      struct
      {
    uint16_t source;
    uint16_t dest;
    uint32_t seq;
    uint32_t ack_seq;
# if __BYTE_ORDER == __LITTLE_ENDIAN
    uint16_t res1:4;
    uint16_t doff:4;
    uint16_t fin:1;
    uint16_t syn:1;
    uint16_t rst:1;
    uint16_t psh:1;
    uint16_t ack:1;
    uint16_t urg:1;
    uint16_t res2:2;
# elif __BYTE_ORDER == __BIG_ENDIAN
    uint16_t doff:4;
    uint16_t res1:4;
    uint16_t res2:2;
    uint16_t urg:1;
    uint16_t ack:1;
    uint16_t psh:1;
    uint16_t rst:1;
    uint16_t syn:1;
    uint16_t fin:1;
# else
#  error "Adjust your <bits/endian.h> defines"
# endif
    uint16_t window;
    uint16_t check;
    uint16_t urg_ptr;
      };
    };
};

做 TCP 警告意味著資料包被忽略,

uj5u.com熱心網友回復:

為了得到問題的答案。

OP 正在嘗試創建一個 SYNACK 資料包來回答傳入的 SYN 資料包。TCP SYN 資料包從作業系統堆疊生成,并使用選項。

Wireshark 抱怨標題太短。可以看出,tcp頭中的頭長度設定為40個位元組,而實際存在的頭只有20個位元組(整個資料包為40個位元組:20個位元組的IP頭和20個位元組的tcp頭)。

問題是欄位tcp->doff,即 tcp 標頭,長度是從傳入的 SYN 資料包中復制的。盡管未顯示,但傳入的 SYN 資料包中可能包含 TCP 選項,因此其標頭為 40 位元組,而不是 20 位元組。因此,復制tcp->doff會導致出現問題的錯誤訊息。

供參考,tcp 頭長度欄位是 tcp 頭長度的 32 位的倍數,或 4 個位元組。最小 tcp 標頭為 20 位元組或 5 個 tcp 標頭單元。或者也tcp->doff = sizeof(struct tcphdr)/4應該作業。

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

標籤:C 插座 通讯协议

上一篇:一個關于python中sockets加密的問題

下一篇:檢查埠是否在Python3中打開?

標籤雲
其他(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