




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、負載均衡器軟件 開發(fā)報告 院系:班級: 成員:目錄1.可行性分析報告11.1 項目背景11.2產品分析11.3 結論意見22.項目開發(fā)計劃22.1 總體功能要求22.2 軟件開發(fā)平臺要求22.3 軟件項目的開發(fā)實施過程管理要求33.軟件開發(fā)33.1 軟件的需求分析 33.3軟件的詳細設計53.4 軟件的編碼63.5軟件的測試313.5.1測試計劃313.5.2 軟件測試324.項目開發(fā)總結報告33I1.可行性分析報告1.1 項目背景面對龐大的數據流量,面對集中性的訪問,是不是覺得網絡服務器岌岌可危呢?不用怕,負載均衡器就能幫你緩解這個問題。負載均衡器通過虛擬IP地址方法,解決了輪流排
2、程所面臨的許多問題。使用了負載均衡器集群系統(tǒng),在外部看來,像是具有一個IP地址的單一服務器一樣,當然,這個IP地址是虛擬的,它映射了集群中的每一臺機器的地址。所以,在某種程度上,負載均衡器是將整個集群的IP地址報漏給外部網絡。當請求到達負載均衡器時,它會重寫該請求的頭文件,并將之指定到集群中的機器上。如果某臺機器被從集群中移除了,請求不會別發(fā)往已經不存在的服務器上,因為所有的機器表面上都具有同一個IP地址,即使集群中的某個節(jié)點被移除了,該地址也不會發(fā)生變化。而且,internet上緩存的DNS條目也不再是問題了。當返回一個應答時,客戶端看到的只是從負載均衡器上所返回的結果。也就是說,客戶端操作
3、的對象是負載均衡器,對于其更后端的操作,對客戶端來講,是完全透明的。1.2產品分析服務器一致性負載均衡器讀取客戶端發(fā)出的每一個請求中所包含的cookies或url解釋?;谒x出的這些信息,負載均衡器就可以重寫報頭并將請求發(fā)往集群中合適的節(jié)點上,該節(jié)點維護著相應客戶端請求的會話信息。在HTTP通信中,負載均衡器可以提供服務器一致性,但并不是通過一個安全的途徑(例如:HTTPS)來提供這種服務。當消息被加密后(SSL),負載均衡器就不能讀出隱藏在其中的會話信息。通過故障恢復機制獲得高可靠性故障恢復發(fā)生在當集群中某個節(jié)點不能處理請求,需將請求重新導向到其他節(jié)點時。主要有兩種故障恢復:請求級故障恢復
4、。當集群中的一個節(jié)點不能處理請求時(通常是由于down機),請求被發(fā)送到其他節(jié)點。當然,在導向到其他節(jié)點的同時,保存在原節(jié)點上的會話信息將會丟失。透明會話故障恢復。當一個引用失敗后,負載均衡器會將之發(fā)送到集群中其他的節(jié)點上,以完成操作,這一點對用戶來說是透明的。由于透明會話故障恢復需要節(jié)點具備相應的操作信息,因此為了實現(xiàn)該功能,集群中的所有節(jié)點必須具有公共存儲區(qū)域或通用數據庫,存儲會話信息數據,以提供每個節(jié)點在進行單獨進程會話故障恢復時所需要的操作信息。既然所有的Web應用請求都必須經過負載均衡系統(tǒng),那么系統(tǒng)就可以確定活動會話的數量,在任何實例訪問中的活動會話的數目,應答的次數,高峰負載次數,
5、以及在高峰期和低谷期的會話的數目,還有其他更多的。所有的這些統(tǒng)計信息都可以被很好的用來調整整個系統(tǒng)的性能。1.3 結論意見雖然此項目存在一定的技術難度和風險,但我們對項目要達到的目標十分清楚,對所要開發(fā)系統(tǒng)將要實現(xiàn)的功能也非常了解。而且有一些成品作為參考,并且在項目的實施過程中我們能夠獲得幫助,我認為只要我們能夠認真思考、仔細規(guī)劃、明確分工,我們可以承擔此項目的開發(fā)。2.項目開發(fā)計劃2.1 總體功能要求1.擴展網絡設備和服務器的帶寬2.增加吞吐量3.加強網絡數據處理能力4.提高網絡的靈活性和可用性2.2 軟件開發(fā)平臺要求Visual c+ 6.0SQL Server 2008C+ Builde
6、r網絡架構:完全支持TCP/IP協(xié)議2.3 軟件項目的開發(fā)實施過程管理要求3.軟件開發(fā)3.1 軟件的需求分析 1DNS負載均衡最早的負載均衡技術是通過DNS來實現(xiàn)的,在DNS中為多個地址配置同一個名字,因而查詢這個名字的客戶機將得到其中一個地址,從而使得不同的客戶訪問不同的服務器,達到負載均衡的目的。DNS負載均衡是一種簡單而有效的方法,但是它不能區(qū)分服務器的差異,也不能反映服務器的當前運行狀態(tài)。 2代理服務器負載均衡 使用代理服務器,可以將請求轉發(fā)給內部的服務器,使用這種加速模式顯然可以提升靜態(tài)網頁的訪問速度。然而,也可以考慮這樣一種技術,使用代理服務器將請求均
7、勻轉發(fā)給多臺服務器,從而達到負載均衡的目的。 3地址轉換網關負載均衡 支持負載均衡的地址轉換網關,可以將一個外部IP地址映射為多個內部IP地址,對每次TCP連接請求動態(tài)使用其中一個內部地址,達到負載均衡的目的。 4協(xié)議內部支持負載均衡除了這三種負載均衡方式之外,有的協(xié)議內部支持與負載均衡相關的功能,例如HTTP協(xié)議中的重定向能力等,HTTP運行于TCP連接的最高層。 5NAT負載均衡NAT簡單地說就是將一個IP地址轉換為另一個IP地址,一般用于未經注冊的內部地址與合法的、已獲注冊的Internet IP地址間進行轉換。適用于解決Internet
8、 IP地址緊張、不想讓網絡外部知道內部網絡結構等的場合下。 6反向代理負載均衡普通代理方式是代理內部網絡用戶訪問internet上服務器的連接請求,客戶端必須指定代理服務器,并將本來要直接發(fā)送到internet上服務器的連接請求發(fā)送給代理服務器處理。反向代理(Reverse Proxy)方式是指以代理服務器來接受internet上的連接請求,然后將請求轉發(fā)給內部網絡上的服務器,并將從服務器上得到的結果返回給internet上請求連接的客戶端,此時代理服務器對外就表現(xiàn)為一個服務器。反向代理負載均衡技術是把將來自internet上的連接請求以反向代理的方式動態(tài)地轉發(fā)給
9、內部網絡上的多臺服務器進行處理,從而達到負載均衡的目的。 7混合型負載均衡在有些大型網絡,由于多個服務器群內硬件設備、各自的規(guī)模、提供的服務等的差異,可以考慮給每個服務器群采用最合適的負載均衡方式,然后又在這多個服務器群間再一次負載均衡或群集起來以一個整體向外界提供服務(即把這多個服務器群當做一個新的服務器群),從而達到最佳的性能。將這種方式稱之為混合型負載均衡。此種方式有時也用于單臺均衡設備的性能不能滿足大量連接請求的情況下。3.2軟件的概要設計 軟件負載均衡解決方案是指在一臺或多臺服務器相應的操作系統(tǒng)上安裝一個或多個附加軟件來實現(xiàn)負載均衡,DNSLoadBalanceC
10、heckPointFirewall-1ConnectControl等,它的優(yōu)點是基于特定環(huán)境,配置簡單,使用靈活,成本低廉,可以滿足一般的負載均衡需求。硬件負載均衡解決方案是直接在服務器和外部網絡間安裝負載均衡設備,這種設備通常稱之為負載均衡器,由于專門的設備完成專門的任務,獨立于操作系統(tǒng),整體性能得到大量提高,加上多樣化的負載均衡策略,智能化的流量管理,可達到最佳的負載均衡需求。一般而言,硬件負載均衡在功能、性能上優(yōu)于軟件方式,不過成本昂貴。本地負載均衡能有效地解決數據流量過大、網絡負荷過重的問題,并且不需花費昂貴開支購置性能卓越的服務器,充分利用現(xiàn)有設備,避免服務器單點故障造成數據流量的損
11、失。其有靈活多樣的均衡策略把數據流量合理地分配給服務器群內的服務器共同負擔。即使是再給現(xiàn)有服務器擴充升級,也只是簡單地增加一個新的服務器到服務群中,而不需改變現(xiàn)有網絡結構、停止現(xiàn)有的服務。全局負載均衡主要用于在一個多區(qū)域擁有自己服務器的站點,為了使全球用戶只以一個IP地址或域名就能訪問到離自己最近的服務器,從而獲得最快的訪問速度,也可用于子公司分散站點分布廣的大公司通過企業(yè)內部互聯(lián)網來達到資源統(tǒng)一合理分配的目的。3.3軟件的詳細設計1.輪轉法:輪轉算法是所有調度算法中最簡單也最容易實現(xiàn)的一種方法。在一個任務隊列里,隊列的每個成員(節(jié)點)都具有相同的地位,輪轉法簡單的在這組成員中順序輪轉選擇。在
12、負載平衡環(huán)境中,均衡器將新的請求輪流發(fā)給節(jié)點隊列中的下一節(jié)點,如此連續(xù)、周而復始,每個集群的節(jié)點都在相等的地位下被輪流選擇。這個算法在DNS域名輪詢中被廣泛使用。 輪轉法的活動是可預知的,每個節(jié)點被選擇的機會是1/N,因此很容易計算出節(jié)點的負載分布。輪轉法典型的適用于集群中所有節(jié)點的處理能力和性能均相同的情況,在實際應用中,一般將它與其他簡單方法聯(lián)合使用時比較有效。2.散列法:散列法也叫哈希法(HASH),通過單射不可逆的HASH函數,按照某種規(guī)則將網絡請求發(fā)往集群節(jié)點。哈希法在其他幾類平衡算法不是很有效時會顯示出特別的威力。例如,在前面提到的UDP會話的情況下,由于輪轉法和其他幾類基于連接信
13、息的算法,無法識別出會話的起止標記,會引起應用混亂。 而采取基于數據包源地址的哈希映射可以在一定程度上解決這個問題:將具有相同源地址的數據包發(fā)給同一服務器節(jié)點,這使得基于高層會話的事務可以以適當的方式運行。相對稱的是,基于目的地址的哈希調度算法可以用在Web Cache集群中,指向同一個目標站點的訪問請求都被負載平衡器發(fā)送到同一個Cache服務節(jié)點上,以避免頁面缺失而帶來的更新Cache問題。3.最少連接法:在最少連接法中,平衡器紀錄目前所有活躍連接,把下一個新的請求發(fā)給當前含有最少連接數的節(jié)點。這種算法針對TCP連接進行,但由于不同應用對系統(tǒng)資源的消耗可能差異很大,而連接數無法反映出真實的應
14、用負載,因此在使用重型Web服務器作為集群節(jié)點服務時(例如Apache服務器),該算法在平衡負載的效果上要打個折扣。為了減少這個不利的影響,可以對每個節(jié)點設置最大的連接數上限(通過閾值設定體現(xiàn))。4.最低缺失法:在最低缺失法中,平衡器長期紀錄到各節(jié)點的請求情況,把下個請求發(fā)給歷史上處理請求最少的節(jié)點。與最少連接法不同的是,最低缺失記錄過去的連接數而不是當前的連接數。5.最快響應法:平衡器記錄自身到每一個集群節(jié)點的網絡響應時間,并將下一個到達的連接請求分配給響應時間最短的節(jié)點,這種方法要求使用ICMP包或基于UDP包的專用技術來主動探測各節(jié)點。 在大多數基于LAN的集群中,最快響應算法工作的并不
15、是很好,因為LAN中的ICMP包基本上都在10ms內完成回應,體現(xiàn)不出節(jié)點之間的差異;如果在 WAN上進行平衡的話,響應時間對于用戶就近選擇服務器而言還是具有現(xiàn)實意義的;而且集群的拓撲越分散這種方法越能體現(xiàn)出效果來。這種方法是高級平衡基于拓撲結構重定向用到的主要方法。6. 加權法:加權方法只能與其他方法合用,是它們的一個很好的補充。加權算法根據節(jié)點的優(yōu)先級或當前的負載狀況(即權值)來構成負載平衡的多優(yōu)先級隊列,隊列中的每個等待處理的連接都具有相同處理等級,這樣在同一個隊列里可以按照前面的輪轉法或者最少連接法進行均衡,而隊列之間按照優(yōu)先級的先后順序進行均衡處理。在這里權值是基于各節(jié)點能力的一個估
16、計值。3.4 軟件的編碼#include <exception>#include <errno.h>#include <string.h>#include "conn.h"#include "log.h"#include "fdwrapper.h"conn:conn() m_srvfd = -1; m_clt_buf = new char BUF_SIZE ; if( !m_clt_buf ) throw std:exception(); m_srv_buf = new char BUF_SIZE
17、; if( !m_srv_buf ) throw std:exception(); reset();conn:conn() delete m_clt_buf; delete m_srv_buf;void conn:init_clt( int sockfd, const sockaddr_in& client_addr ) m_cltfd = sockfd; m_clt_address = client_addr;void conn:init_srv( int sockfd, const sockaddr_in& server_addr ) m_srvfd = sockfd; m
18、_srv_address = server_addr;void conn:reset() m_clt_read_idx = 0; m_clt_write_idx = 0; m_srv_read_idx = 0; m_srv_write_idx = 0; m_srv_closed = false; m_cltfd = -1; memset( m_clt_buf, '0', BUF_SIZE ); memset( m_srv_buf, '0', BUF_SIZE );RET_CODE conn:read_clt() int bytes_read = 0; while
19、( true ) if( m_clt_read_idx >= BUF_SIZE ) log( LOG_ERR, _FILE_, _LINE_, "%s", "the client read buffer is full, let server write" ); return BUFFER_FULL; bytes_read = recv( m_cltfd, m_clt_buf + m_clt_read_idx, BUF_SIZE - m_clt_read_idx, 0 ); if ( bytes_read = -1 ) if( errno = EA
20、GAIN | errno = EWOULDBLOCK ) break; return IOERR; else if ( bytes_read = 0 ) return CLOSED; m_clt_read_idx += bytes_read; return ( ( m_clt_read_idx - m_clt_write_idx ) > 0 ) ? OK : NOTHING;RET_CODE conn:read_srv() int bytes_read = 0; while( true ) if( m_srv_read_idx >= BUF_SIZE ) log( LOG_ERR,
21、 _FILE_, _LINE_, "%s", "the server read buffer is full, let client write" ); return BUFFER_FULL; bytes_read = recv( m_srvfd, m_srv_buf + m_srv_read_idx, BUF_SIZE - m_srv_read_idx, 0 ); if ( bytes_read = -1 ) if( errno = EAGAIN | errno = EWOULDBLOCK ) break; return IOERR; else if
22、( bytes_read = 0 ) log( LOG_ERR, _FILE_, _LINE_, "%s", "the server should not close the persist connection" ); return CLOSED; m_srv_read_idx += bytes_read; return ( ( m_srv_read_idx - m_srv_write_idx ) > 0 ) ? OK : NOTHING;RET_CODE conn:write_srv() int bytes_write = 0; while(
23、true ) if( m_clt_read_idx <= m_clt_write_idx ) m_clt_read_idx = 0; m_clt_write_idx = 0; return BUFFER_EMPTY; bytes_write = send( m_srvfd, m_clt_buf + m_clt_write_idx, m_clt_read_idx - m_clt_write_idx, 0 ); if ( bytes_write = -1 ) if( errno = EAGAIN | errno = EWOULDBLOCK ) return TRY_AGAIN; log( L
24、OG_ERR, _FILE_, _LINE_, "write server socket failed, %s", strerror( errno ) ); return IOERR; else if ( bytes_write = 0 ) return CLOSED; m_clt_write_idx += bytes_write; RET_CODE conn:write_clt() int bytes_write = 0; while( true ) if( m_srv_read_idx <= m_srv_write_idx ) m_srv_read_idx = 0
25、; m_srv_write_idx = 0; return BUFFER_EMPTY; bytes_write = send( m_cltfd, m_srv_buf + m_srv_write_idx, m_srv_read_idx - m_srv_write_idx, 0 ); if ( bytes_write = -1 ) if( errno = EAGAIN | errno = EWOULDBLOCK ) return TRY_AGAIN; log( LOG_ERR, _FILE_, _LINE_, "write client socket failed, %s",
26、strerror( errno ) ); return IOERR; else if ( bytes_write = 0 ) return CLOSED; m_srv_write_idx += bytes_write; #ifndef FDWRAPPER_H#define FDWRAPPER_H#include <unistd.h>#include <fcntl.h>#include <sys/epoll.h>int setnonblocking( int fd ) int old_option = fcntl( fd, F_GETFL ); int new
27、_option = old_option | O_NONBLOCK; fcntl( fd, F_SETFL, new_option ); return old_option;void add_read_fd( int epollfd, int fd ) epoll_event event; event.data.fd = fd; event.events = EPOLLIN | EPOLLET; epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event ); setnonblocking( fd );void add_write_fd( int epo
28、llfd, int fd ) epoll_event event; event.data.fd = fd; event.events = EPOLLOUT | EPOLLET; epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event ); setnonblocking( fd );void closefd( int epollfd, int fd ) epoll_ctl( epollfd, EPOLL_CTL_DEL, fd, 0 ); close( fd );void removefd( int epollfd, int fd ) epoll_ct
29、l( epollfd, EPOLL_CTL_DEL, fd, 0 );void modfd( int epollfd, int fd, int ev ) epoll_event event; event.data.fd = fd; event.events = ev | EPOLLET; epoll_ctl( epollfd, EPOLL_CTL_MOD, fd, &event );#endif#include <stdio.h>#include <time.h>#include <string.h>#include "log.h"
30、;static int level = LOG_INFO;static int LOG_BUFFER_SIZE = 2048;static const char* loglevels = "emerge!", "alert!", "critical!", "error!", "warn!", "notice:", "info:", "debug:"void set_loglevel( int log_level ) level = lo
31、g_level;void log( int log_level, const char* file_name, int line_num, const char* format, . ) if ( log_level > level ) return; time_t tmp = time( NULL ); struct tm* cur_time = localtime( &tmp ); if ( ! cur_time ) return; char arg_buffer LOG_BUFFER_SIZE ; memset( arg_buffer, '0', LOG_B
32、UFFER_SIZE ); strftime( arg_buffer, LOG_BUFFER_SIZE - 1, " %x %X ", cur_time ); printf( "%s", arg_buffer ); printf( "%s:%04d ", file_name, line_num ); printf( "%s ", loglevels log_level - LOG_EMERG ); va_list arg_list; va_start( arg_list, format ); memset( arg
33、_buffer, '0', LOG_BUFFER_SIZE ); vsnprintf( arg_buffer, LOG_BUFFER_SIZE - 1, format, arg_list ); printf( "%sn", arg_buffer ); fflush( stdout ); va_end( arg_list );#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#incl
34、ude <assert.h>#include <stdio.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <fcntl.h>#include <stdlib.h>#include <sys/epoll.h>#include <signal.h>#include <sys/wait.h>#include <sys/stat.h>#include <vector>#in
35、clude "log.h"#include "conn.h"#include "mgr.h"#include "processpool.h"using std:vector;static const char* version = "1.0"static void usage( const char* prog ) log( LOG_INFO, _FILE_, _LINE_, "usage: %s -h -v -f config_file", prog );int main(
36、 int argc, char* argv ) char cfg_file1024; memset( cfg_file, '0', 100 ); int option; while ( ( option = getopt( argc, argv, "f:xvh" ) ) != -1 ) switch ( option ) case 'x': set_loglevel( LOG_DEBUG ); break; case 'v': log( LOG_INFO, _FILE_, _LINE_, "%s %s",
37、argv0, version ); return 0; case 'h': usage( basename( argv 0 ) ); return 0; case 'f': memcpy( cfg_file, optarg, strlen( optarg ) ); break; case '?': log( LOG_ERR, _FILE_, _LINE_, "un-recognized option %c", option ); usage( basename( argv 0 ) ); return 1; if( cfg_fi
38、le0 = '0' ) log( LOG_ERR, _FILE_, _LINE_, "%s", "please specifiy the config file" ); return 1; int cfg_fd = open( cfg_file, O_RDONLY ); if( !cfg_fd ) log( LOG_ERR, _FILE_, _LINE_, "read config file met error: %s", strerror( errno ) ); return 1; struct stat ret_s
39、tat; if( fstat( cfg_fd, &ret_stat ) < 0 ) log( LOG_ERR, _FILE_, _LINE_, "read config file met error: %s", strerror( errno ) ); return 1; char* buf = new char ret_stat.st_size + 1; memset( buf, '0', ret_stat.st_size + 1 ); ssize_t read_sz = read( cfg_fd, buf, ret_stat.st_size
40、 ); if ( read_sz < 0 ) log( LOG_ERR, _FILE_, _LINE_, "read config file met error: %s", strerror( errno ) ); return 1; vector< host > balance_srv; vector< host > logical_srv; host tmp_host; memset( tmp_host.m_hostname, '0', 1024 ); char* tmp_hostname; char* tmp_port;
41、char* tmp_conncnt; bool opentag = false; char* tmp = buf; char* tmp2 = NULL; char* tmp3 = NULL; char* tmp4 = NULL; while( tmp2 = strpbrk( tmp, "n" ) ) *tmp2+ = '0' if( strstr( tmp, "<logical_host>" ) ) if( opentag ) log( LOG_ERR, _FILE_, _LINE_, "%s", &quo
42、t;parse config file failed" ); return 1; opentag = true; else if( strstr( tmp, "</logical_host>" ) ) if( !opentag ) log( LOG_ERR, _FILE_, _LINE_, "%s", "parse config file failed" ); return 1; logical_srv.push_back( tmp_host ); memset( tmp_host.m_hostname,
43、9;0', 1024 ); opentag = false; else if( tmp3 = strstr( tmp, "<name>" ) ) tmp_hostname = tmp3 + 6; tmp4 = strstr( tmp_hostname, "</name>" ); if( !tmp4 ) log( LOG_ERR, _FILE_, _LINE_, "%s", "parse config file failed" ); return 1; *tmp4 = '0
44、39; memcpy( tmp_host.m_hostname, tmp_hostname, strlen( tmp_hostname ) ); else if( tmp3 = strstr( tmp, "<port>" ) ) tmp_port = tmp3 + 6; tmp4 = strstr( tmp_port, "</port>" ); if( !tmp4 ) log( LOG_ERR, _FILE_, _LINE_, "%s", "parse config file failed"
45、 ); return 1; *tmp4 = '0' tmp_host.m_port = atoi( tmp_port ); else if( tmp3 = strstr( tmp, "<conns>" ) ) tmp_conncnt = tmp3 + 7; tmp4 = strstr( tmp_conncnt, "</conns>" ); if( !tmp4 ) log( LOG_ERR, _FILE_, _LINE_, "%s", "parse config file failed&
46、quot; ); return 1; *tmp4 = '0' tmp_host.m_conncnt = atoi( tmp_conncnt ); else if( tmp3 = strstr( tmp, "Listen" ) ) tmp_hostname = tmp3 + 6; tmp4 = strstr( tmp_hostname, ":" ); if( !tmp4 ) log( LOG_ERR, _FILE_, _LINE_, "%s", "parse config file failed" )
47、; return 1; *tmp4+ = '0' tmp_host.m_port = atoi( tmp4 ); memcpy( tmp_host.m_hostname, tmp3, strlen( tmp3 ) ); balance_srv.push_back( tmp_host ); memset( tmp_host.m_hostname, '0', 1024 ); tmp = tmp2; if( balance_srv.size() = 0 | logical_srv.size() = 0 ) log( LOG_ERR, _FILE_, _LINE_, &
48、quot;%s", "parse config file failed" ); return 1; const char* ip = balance_srv0.m_hostname; int port = balance_srv0.m_port; int listenfd = socket( PF_INET, SOCK_STREAM, 0 ); assert( listenfd >= 0 ); int ret = 0; struct sockaddr_in address; bzero( &address, sizeof( address ) );
49、address.sin_family = AF_INET; inet_pton( AF_INET, ip, &address.sin_addr ); address.sin_port = htons( port ); ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) ); assert( ret != -1 ); ret = listen( listenfd, 5 ); assert( ret != -1 ); /memset( cfg_host.m_hostname, '0
50、9;, 1024 ); /memcpy( cfg_host.m_hostname, "", strlen( "" ) ); /cfg_host.m_port = 54321; /cfg_host.m_conncnt = 5; processpool< conn, host, mgr >* pool = processpool< conn, host, mgr >:create( listenfd, logical_srv.size() ); if( pool ) pool->run( logical_srv ); delete pool; close( listenfd ); return 0;#incl
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年電子合同法律適用與實踐探討
- 2025橋梁建設施工合同
- 2025建筑施工機械租賃合同模板
- 2025寫字間租賃合同樣本
- 2025個體健身房器材特許經營合同
- 2025商業(yè)大廈與裝修公司合作的合同
- 2025臨時建筑買賣合同模板
- 《2025機械設備租賃合同》
- 實習勞動合同方協(xié)議
- 風險代理合同范本
- 《中國傳統(tǒng)圖案》課件
- 手術體位經典課件
- 【基于STM32單片機無線藍牙耳機設計5400字(論文)】
- 密碼應用安全性評估
- 西班牙社會與文化智慧樹知到課后章節(jié)答案2023年下天津外國語大學
- 2021上海慢行交通規(guī)劃設計導則
- 浙江省紹興市2023年中考英語真題(附答案)
- 廢品站勞務合同范本
- 安全生產管理規(guī)章制度評審記錄
- 教科版五年級科學下冊全套測試卷
- 建設工程工程量清單及清單計價2013
評論
0/150
提交評論