新聞中心
在今天的互聯(lián)網(wǎng)時(shí)代,網(wǎng)絡(luò)通信已經(jīng)成為了各種應(yīng)用程序中不可或缺的一部分。而TCP協(xié)議則是現(xiàn)代網(wǎng)絡(luò)通信的主要標(biāo)準(zhǔn)之一,它為不同的應(yīng)用程序提供了高效、可靠的數(shù)據(jù)傳輸服務(wù)。因此,為了構(gòu)建一個(gè)高效穩(wěn)定的網(wǎng)絡(luò)通信系統(tǒng),我們需要學(xué)習(xí)如何構(gòu)建一個(gè)優(yōu)秀的TCP服務(wù)器。

在本文中,我們將會(huì)討論一些關(guān)于構(gòu)建Linux TCP服務(wù)器的基本知識(shí)和技能,包括如何設(shè)置和優(yōu)化服務(wù)器,如何使用多線程、多進(jìn)程、I/O多路復(fù)用和異步I/O等技術(shù),以此為基礎(chǔ)手動(dòng)構(gòu)建出高效穩(wěn)定的TCP服務(wù)器。
之一步:服務(wù)器的配置
構(gòu)建一個(gè)高效穩(wěn)定的TCP服務(wù)器需要首先對(duì)服務(wù)器進(jìn)行配置。服務(wù)器的配置包括設(shè)置和優(yōu)化TCP參數(shù)以及優(yōu)化操作系統(tǒng)的配置。在這一步,我們將會(huì)了解一些最基本的TCP參數(shù)和操作系統(tǒng)配置項(xiàng)的設(shè)置,以保證服務(wù)器能夠具有更佳的性能表現(xiàn)。
TCP參數(shù)設(shè)置
TCP參數(shù)是影響服務(wù)器性能的最重要的因素之一。其中最基本的參數(shù)包括TCP窗口大小、MSS等。下面是一些常見(jiàn)的TCP參數(shù)設(shè)置:
1. TCP窗口大小
TCP窗口大小是指數(shù)據(jù)量的一種計(jì)算方式,在TCP連接的初始化過(guò)程中會(huì)進(jìn)行設(shè)置。而TCP窗口大小的設(shè)置會(huì)直接影響到服務(wù)器的性能表現(xiàn)。在Linux系統(tǒng)上,可以通過(guò)修改sysctl.conf文件中的net.core.wmem_max、net.core.rmem_max、net.ipv4.tcp_wmem和net.ipv4.tcp_rmem等參數(shù)進(jìn)行優(yōu)化,以提高TCP窗口大小。
2. Nagle算法
Nagle算法是用于優(yōu)化TCP網(wǎng)絡(luò)通信的一個(gè)重要算法。在默認(rèn)情況下,Nagle算法會(huì)將應(yīng)用程序發(fā)送的小數(shù)據(jù)包合并為一個(gè)更大的數(shù)據(jù)包再進(jìn)行發(fā)送,以減少網(wǎng)絡(luò)通信的次數(shù)。但在對(duì)于實(shí)時(shí)性要求較高的應(yīng)用中,可以關(guān)閉Nagle算法來(lái)提高TCP網(wǎng)絡(luò)通信的速度。
操作系統(tǒng)配置項(xiàng)設(shè)置
操作系統(tǒng)的配置項(xiàng)設(shè)置是構(gòu)建高效穩(wěn)定的TCP服務(wù)器的另一個(gè)重要組成部分。在本文中,我們將會(huì)介紹一些常見(jiàn)的操作系統(tǒng)配置項(xiàng),以提高服務(wù)器的性能表現(xiàn)。
1. 使用最新的內(nèi)核
使用最新的內(nèi)核可以獲取到所有最新的性能改進(jìn)和優(yōu)化。因此,我們建議使用最新的操作系統(tǒng)版本,以保證服務(wù)器的性能表現(xiàn)。
2. 關(guān)閉不必要的服務(wù)
在服務(wù)器運(yùn)行時(shí),關(guān)閉不必要的進(jìn)程和服務(wù)可以顯著提高服務(wù)器性能。因此,在構(gòu)建高效穩(wěn)定的TCP服務(wù)器時(shí),我們應(yīng)該關(guān)閉所有不必要的服務(wù)和進(jìn)程,從而保證服務(wù)器的穩(wěn)定運(yùn)行。
第二步:使用多進(jìn)程和多線程技術(shù)
在現(xiàn)代操作系統(tǒng)中,多進(jìn)程和多線程可以幫助服務(wù)器使用不同的CPU核心,提高服務(wù)器的性能。在使用多線程和多進(jìn)程技術(shù)時(shí),我們需要注意以下幾點(diǎn):
1. 在使用多線程技術(shù)時(shí),需要注意線程安全問(wèn)題。
2. 在使用多進(jìn)程技術(shù)時(shí),需要注意進(jìn)程通信問(wèn)題。
3. 在使用多線程和多進(jìn)程技術(shù)時(shí),需要合理使用CPU核心,避免CPU資源的浪費(fèi)。
第三步:使用I/O多路復(fù)用和異步I/O技術(shù)
I/O多路復(fù)用和異步I/O技術(shù)是構(gòu)建高效穩(wěn)定的TCP服務(wù)器的另一個(gè)重要組成部分。這些技術(shù)可以幫助服務(wù)器在處理多個(gè)網(wǎng)絡(luò)請(qǐng)求時(shí)提高效率,從而更快地響應(yīng)客戶端請(qǐng)求。
在使用I/O多路復(fù)用和異步I/O技術(shù)時(shí),需要注意以下幾點(diǎn):
1. 在使用I/O多路復(fù)用技術(shù)時(shí),需要注意同時(shí)處理多個(gè)I/O事件時(shí)的問(wèn)題,防止出現(xiàn)死鎖等情況。
2. 在使用異步I/O技術(shù)時(shí),需要注意I/O事件發(fā)生的順序,以避免出現(xiàn)數(shù)據(jù)錯(cuò)誤等不良情況。
結(jié)論
Linux TCP服務(wù)器是構(gòu)建高效穩(wěn)定的網(wǎng)絡(luò)通信的一個(gè)關(guān)鍵部分。在本文中,我們介紹了一些關(guān)于如何構(gòu)建高效穩(wěn)定的TCP服務(wù)器的基本知識(shí)和技能。在實(shí)際的應(yīng)用中,我們應(yīng)該針對(duì)不同的應(yīng)用場(chǎng)景制定不同的優(yōu)化策略,以保證服務(wù)器的更佳性能表現(xiàn)。
相關(guān)問(wèn)題拓展閱讀:
- linux python connect 對(duì)同一個(gè)端口可以建立多少個(gè)
- Linux下 client server 連不上
linux python connect 對(duì)同一個(gè)端口可以建立多少個(gè)
如果是tcp client用同一個(gè)本地端口去連不同的兩個(gè)服務(wù)器ip,連第二個(gè)時(shí)就會(huì)提示端口已被占用。但服務(wù)器的監(jiān)聽(tīng)端口,可以accept多次,建立多個(gè)socket;我的問(wèn)題是服務(wù)器一個(gè)端口為什么能建立多個(gè)連敗櫻接而客戶端卻不行呢?
TCP server 可以,TCP client 也可以。一個(gè)套接字只能建立一個(gè)連接,無(wú)論對(duì)于 server 還是 client。
注意報(bào)錯(cuò)消息是:
(EISCONN) Transport endpoint is already connected
man 2 connect 說(shuō)得很清楚了:
Generally, connection-based protocol sockets may successfully connect() only once; connectionless protocol sockets may use connect() multiple times to change their association.
就是說(shuō),TCP 套接字最多只能調(diào)用 connect 一次。那么,你的監(jiān)聽(tīng)套接字調(diào)用 connect 了幾次?
來(lái)點(diǎn)有意思的。
一個(gè)套接字不能連接兩次,并不代表一個(gè)本地地址不能用兩次,看!****加粗文字**加做并粗文字**
>>> import socket
>>> s = socket.socket()
# since Linux 3.9, 見(jiàn) man 7 socket
>>> s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
>>> s2 = socket.socket()
>>> s2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
>>> s.bind((‘127.0.0.1’, 12345))
>>> s2.bind((‘127.0.0.1’, 12345))
# 都可以使用同一本地地址來(lái)連接哦
>>> s.connect((‘127.0.0.1’, 80))
>>> s2.connect((‘127.0.0.1’, 4321))
>>> netstat -npt | grep 12345
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 127.0.0.1:127.0.0.1:ESTABLISHED 18284/python3
tcp 0 127.0.0.1:127.0.0.1:ESTABLISHED 4568/python3
tcp 0 127.0.0.1:127.0.0.1:ESTABLISHED –
tcp 0 127.0.0.1:127.0.0.1:ESTABLISHED 4568/python3
你們這些有女友的都弱爆了啦
更新:大家來(lái)玩 TCP: 一個(gè)人也可以建立 TCP 連接呢 – 依云’s Blog
2023年08月19日回答 · 2023年08月19日更新
依云21.1k 聲望
答案對(duì)人有幫助,有參考價(jià)值1答案沒(méi)幫助,是錯(cuò)誤的答案,答非所問(wèn)
內(nèi)核是以一個(gè)(著名的)5元信息組來(lái)標(biāo)識(shí)不同的socket的:源地址、源端口、目的地址、目的端口、協(xié)議號(hào)。任何一個(gè)不同,都不叫“同一個(gè)socket”。
2023年08月20日回答
sched_yield80 聲望
答案對(duì)人有幫察胡叢助,有參考價(jià)值0答案沒(méi)幫助,是錯(cuò)誤的答案,答非所問(wèn)
首先,TCP鏈接是可靠的端對(duì)端的鏈接,每個(gè)TCP鏈接由4個(gè)要素組成:2組IP地址(本地和遠(yuǎn)端),2組端口地址(本地和遠(yuǎn)端)。其中如果需要跟端口信息綁定時(shí),都需要調(diào)用bind函數(shù),如果server端針對(duì)2個(gè)同樣的IP、端口組進(jìn)行同樣的綁定時(shí),第2次同樣是不成功的。
2023年08月16日回答
charliecui2.4k 聲望
答案對(duì)人有幫助,有參考價(jià)值0答案沒(méi)幫助,是錯(cuò)誤的答案,答非所問(wèn)
有個(gè)相關(guān)的問(wèn)題: ftp的數(shù)據(jù)傳輸,服務(wù)器會(huì)用20端口主動(dòng)連接客戶端,如果兩個(gè)客戶端同時(shí)在一下載東西,那ftp 服務(wù)器能用20端口去連接兩個(gè)ip ?(這時(shí)ftp的服務(wù)器其實(shí)是tcp里的客戶端)
2023年08月16日回答
編輯
hyanleo163 聲望
+1
能啊,看我的實(shí)驗(yàn)。
依云 · 2023年08月19日
不管是服務(wù)器還是客戶端,建立TCP鏈接,同一個(gè)端口都只能使用一次。
這句話其實(shí)是**錯(cuò)的**!
對(duì)于TCP協(xié)議,要成功建立一個(gè)新的鏈接,需要保證新鏈接四個(gè)要素組合體的唯一性:客戶端的IP、客戶端的port、服務(wù)器端的IP、服務(wù)器端的port。也就是說(shuō),服務(wù)器端的同一個(gè)IP和port,可以和同一個(gè)客戶端的多個(gè)不同端口成功建立多個(gè)TCP鏈接(與多個(gè)不同的客戶端當(dāng)然也可以),只要保證【Server IP + Server Port + Client IP + Client Port】這個(gè)組合唯一不重復(fù)即可。
> netstat -a -n -p tcp |grep 9999
tcp.0.0.1:.0.0.1:9999 ESTABLISHED 2701/nc
tcp.0.0.1:.0.0.1:9999 ESTABLISHED 2752/nc
上述結(jié)果127.0.0.1:9999中9999端口成功建立兩個(gè)TCP鏈接,也就可以理解。
**客戶端**發(fā)送TCP鏈接請(qǐng)求的端口,也就是后續(xù)建立TCP鏈接使用的端口,所以一旦TCP鏈接建立,端口就被占用,無(wú)法再建立第二個(gè)鏈接。
而**服務(wù)器端**有兩類(lèi)端口:偵聽(tīng)端口 和 后續(xù)建立TCP鏈接的端口。其中偵聽(tīng)端口只負(fù)責(zé)偵聽(tīng)客戶端發(fā)送來(lái)的TCP鏈接請(qǐng)求,不用作建立TCP鏈接使用,一旦偵聽(tīng)到有客戶端發(fā)送TCP鏈接請(qǐng)求,就分配一個(gè)端口(一般隨機(jī)分配,且不會(huì)重復(fù))用于建立TCP鏈接,而不是所說(shuō)的服務(wù)器一個(gè)端口能建立多個(gè)連接。
上述描述也比較片面,客戶端如何請(qǐng)求及建立鏈接,服務(wù)器端如何偵聽(tīng)及是否分配新隨機(jī)端口等…應(yīng)該都可以在應(yīng)用層面進(jìn)行控制,所以上述描述可以作為建立TCP鏈接的一種方式,僅供參考。
一些英文的參考:
How do multiple clients connect simultaneously to one port, say 80, on a server?
TCP : two different sockets sharing a port?
提升linux下tcp服務(wù)器并發(fā)連接數(shù)限制:30:23
1、修改用戶進(jìn)程可打開(kāi)文件數(shù)限制
在Linux平臺(tái)上,無(wú)論編寫(xiě)客戶端程序還是服務(wù)端程序,在進(jìn)行高并發(fā)TCP連接處理時(shí),更高的并發(fā)數(shù)量都要受到系統(tǒng)對(duì)用戶單一進(jìn)程同時(shí)可打開(kāi)文件數(shù)量的限制(這是因?yàn)橄到y(tǒng)為每個(gè)TCP連接都要?jiǎng)?chuàng)建一個(gè)socket句柄,每個(gè)socket句柄同時(shí)也是一個(gè)文件句柄)。可使用ulimit命令查看系統(tǒng)允許當(dāng)前用戶進(jìn)程打開(kāi)的文件數(shù)限制:
$ ulimit -n
這表示當(dāng)前用戶的每個(gè)進(jìn)程最多允許同時(shí)打開(kāi)1024個(gè)文件,這1024個(gè)文件中還得除去每個(gè)進(jìn)程必然打開(kāi)的標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出,標(biāo)準(zhǔn)錯(cuò)誤,服務(wù)器監(jiān)聽(tīng) socket,進(jìn)程間通訊的unix域socket等文件,那么剩下的可用于客戶端socket連接的文件數(shù)就只有大概=1014個(gè)左右。也就是說(shuō)缺省情況下,基于Linux的通訊程序最多允許同時(shí)1014個(gè)TCP并發(fā)連接。
對(duì)于想支持更高數(shù)量的TCP并發(fā)連接的通訊處理程序,就必須修改Linux對(duì)當(dāng)前用戶的進(jìn)程同時(shí)打開(kāi)的文件數(shù)量的軟限制(soft limit)和硬限制(hardlimit)。其中軟限制是指Linux在當(dāng)前系統(tǒng)能夠承受的范圍內(nèi)進(jìn)一步限制用戶同時(shí)打開(kāi)的文件數(shù);硬限制則是根據(jù)系統(tǒng)硬件資源狀況(主要是系統(tǒng)內(nèi)存)計(jì)算出來(lái)的系統(tǒng)最多可同時(shí)打開(kāi)的文件數(shù)量。通常軟限制小于或等于硬限制。
修改上述限制的最簡(jiǎn)單的辦法就是使用ulimit命令:
$ ulimit -n
上述命令中,在中指定要設(shè)置的單一進(jìn)程允許打開(kāi)的更大文件數(shù)。如果系統(tǒng)回顯類(lèi)似于“Operation notpermitted”之類(lèi)的話,說(shuō)明上述限制修改失敗,實(shí)際上是因?yàn)樵谥兄付ǖ臄?shù)值超過(guò)了Linux系統(tǒng)對(duì)該用戶打開(kāi)文件數(shù)的軟限制或硬限制。因此,就需要修改Linux系統(tǒng)對(duì)用戶的關(guān)于打開(kāi)文件數(shù)的軟限制和硬限制。
之一步,修改/etc/security/limits.conf文件,在文件中添加如下行:
speng soft nofile 10240
speng hard nofile 10240
其中speng指定了要修改哪個(gè)用戶的打開(kāi)文件數(shù)限制,可用’*’號(hào)表示修改所有用戶的限制;soft或hard指定要修改軟限制還是硬限制;10240則指定了想要修改的新的限制值,即更大打開(kāi)文件數(shù)(請(qǐng)注意軟限制值要小于或等于硬限制)。修改完后保存文件。
第二步,修改/etc/pam.d/login文件,在文件中添加如下行:
session required /lib/security/pam_limits.so
這是告訴Linux在用戶完成系統(tǒng)登錄后,應(yīng)該調(diào)用pam_limits.so模塊來(lái)設(shè)置系統(tǒng)對(duì)該用戶可使用的各種資源數(shù)量的更大限制(包括用戶可打開(kāi)的更大文件數(shù)限制),而pam_limits.so模塊就會(huì)從/etc/security/limits.conf文件中讀取配置來(lái)設(shè)置這些限制值。修改完后保存此文件。
第三步,查看Linux系統(tǒng)級(jí)的更大打開(kāi)文件數(shù)限制,使用如下命令:
$ cat /proc/sys/fs/file-max
這表明這臺(tái)Linux系統(tǒng)最多允許同時(shí)打開(kāi)(即包含所有用戶打開(kāi)文件數(shù)總和)12158個(gè)文件,是Linux系統(tǒng)級(jí)硬限制,所有用戶級(jí)的打開(kāi)文件數(shù)限制都不應(yīng)超過(guò)這個(gè)數(shù)值。通常這個(gè)系統(tǒng)級(jí)硬限制是Linux系統(tǒng)在啟動(dòng)時(shí)根據(jù)系統(tǒng)硬件資源狀況計(jì)算出來(lái)的更佳的更大同時(shí)打開(kāi)文件數(shù)限制,如果沒(méi)有特殊需要,不應(yīng)該修改此限制,除非想為用戶級(jí)打開(kāi)文件數(shù)限制設(shè)置超過(guò)此限制的值。修改此硬限制的方法是修改/etc/rc.local腳本,在腳本中添加如下行:
echo> /proc/sys/fs/file-max
這是讓Linux在啟動(dòng)完成后強(qiáng)行將系統(tǒng)級(jí)打開(kāi)文件數(shù)硬限制設(shè)置為22158。修改完后保存此文件。
完成上述步驟后重啟系統(tǒng),一般情況下就可以將Linux系統(tǒng)對(duì)指定用戶的單一進(jìn)程允許同時(shí)打開(kāi)的更大文件數(shù)限制設(shè)為指定的數(shù)值。如果重啟后用 ulimit- n命令查看用戶可打開(kāi)文件數(shù)限制仍然低于上述步驟中設(shè)置的更大值,這可能是因?yàn)樵谟脩舻卿浤_本/etc/profile中使用ulimit-n命令已經(jīng)將用戶可同時(shí)打開(kāi)的文件數(shù)做了限制。由于通過(guò)ulimit-n修改系統(tǒng)對(duì)用戶可同時(shí)打開(kāi)文件的更大數(shù)限制時(shí),新修改的值只能小于或等于上次ulimit-n 設(shè)置的值,因此想用此命令增大這個(gè)限制值是不可能的。所以,如果有上述問(wèn)題存在,就只能去打開(kāi)/etc/profile腳本文件,在文件中查找是否使用了 ulimit-n限制了用戶可同時(shí)打開(kāi)的更大文件數(shù)量,如果找到,則刪除這行命令,或者將其設(shè)置的值改為合適的值,然后保存文件,用戶退出并重新登錄系統(tǒng)即可。
通過(guò)上述步驟,就為支持高并發(fā)TCP連接處理的通訊處理程序解除關(guān)于打開(kāi)文件數(shù)量方面的系統(tǒng)限制。
2、修改網(wǎng)絡(luò)內(nèi)核對(duì)TCP連接的有關(guān)限制
在Linux上編寫(xiě)支持高并發(fā)TCP連接的客戶端通訊處理程序時(shí),有時(shí)會(huì)發(fā)現(xiàn)盡管已經(jīng)解除了系統(tǒng)對(duì)用戶同時(shí)打開(kāi)文件數(shù)的限制,但仍會(huì)出現(xiàn)并發(fā)TCP連接數(shù)增加到一定數(shù)量時(shí),再也無(wú)法成功建立新的TCP連接的現(xiàn)象。出現(xiàn)這種現(xiàn)在的原因有多種。
之一種原因可能是因?yàn)長(zhǎng)inux網(wǎng)絡(luò)內(nèi)核對(duì)本地端口號(hào)范圍有限制。此時(shí),進(jìn)一步分析為什么無(wú)法建立TCP連接,會(huì)發(fā)現(xiàn)問(wèn)題出在connect()調(diào)用返回失敗,查看系統(tǒng)錯(cuò)誤提示消息是“Can’t assign requestedaddress”。同時(shí),如果在此時(shí)用tcpdump工具監(jiān)視網(wǎng)絡(luò),會(huì)發(fā)現(xiàn)根本沒(méi)有TCP連接時(shí)客戶端發(fā)SYN包的網(wǎng)絡(luò)流量。這些情況說(shuō)明問(wèn)題在于本地Linux系統(tǒng)內(nèi)核中有限制。其實(shí),問(wèn)題的根本原因在于Linux內(nèi)核的TCP/IP協(xié)議實(shí)現(xiàn)模塊對(duì)系統(tǒng)中所有的客戶端TCP連接對(duì)應(yīng)的本地端口號(hào)的范圍進(jìn)行了限制(例如,內(nèi)核限制本地端口號(hào)的范圍為1024~32768之間)。當(dāng)系統(tǒng)中某一時(shí)刻同時(shí)存在太多的TCP客戶端連接時(shí),由于每個(gè)TCP客戶端連接都要占用一個(gè)唯一的本地端口號(hào)(此端口號(hào)在系統(tǒng)的本地端口號(hào)范圍限制中),如果現(xiàn)有的TCP客戶端連接已將所有的本地端口號(hào)占滿,則此時(shí)就無(wú)法為新的TCP客戶端連接分配一個(gè)本地端口號(hào)了,因此系統(tǒng)會(huì)在這種情況下在connect()調(diào)用中返回失敗,并將錯(cuò)誤提示消息設(shè)為“Can’t assignrequested address”。有關(guān)這些控制邏輯可以查看Linux內(nèi)核源代碼,以linux2.6內(nèi)核為例,可以查看tcp_ipv4.c文件中如下函數(shù):
static int tcp_v4_hash_connect(struct sock *sk)
請(qǐng)注意上述函數(shù)中對(duì)變量sysctl_local_port_range的訪問(wèn)控制。變量sysctl_local_port_range的初始化則是在tcp.c文件中的如下函數(shù)中設(shè)置:
void __init tcp_init(void)
內(nèi)核編譯時(shí)默認(rèn)設(shè)置的本地端口號(hào)范圍可能太小,因此需要修改此本地端口范圍限制。
之一步,修改/etc/sysctl.conf文件,在文件中添加如下行:
net.ipv4.ip_local_port_range =
這表明將系統(tǒng)對(duì)本地端口范圍限制設(shè)置為1024~65000之間。請(qǐng)注意,本地端口范圍的最小值必須大于或等于1024;而端口范圍的更大值則應(yīng)小于或等于65535。修改完后保存此文件。
第二步,執(zhí)行sysctl命令:
$ sysctl -p
如果系統(tǒng)沒(méi)有錯(cuò)誤提示,就表明新的本地端口范圍設(shè)置成功。如果按上述端口范圍進(jìn)行設(shè)置,則理論上單獨(dú)一個(gè)進(jìn)程最多可以同時(shí)建立60000多個(gè)TCP客戶端連接。
第二種無(wú)法建立TCP連接的原因可能是因?yàn)長(zhǎng)inux網(wǎng)絡(luò)內(nèi)核的IP_TABLE防火墻對(duì)更大跟蹤的TCP連接數(shù)有限制。此時(shí)程序會(huì)表現(xiàn)為在 connect()調(diào)用中阻塞,如同死機(jī),如果用tcpdump工具監(jiān)視網(wǎng)絡(luò),也會(huì)發(fā)現(xiàn)根本沒(méi)有TCP連接時(shí)客戶端發(fā)SYN包的網(wǎng)絡(luò)流量。由于 IP_TABLE防火墻在內(nèi)核中會(huì)對(duì)每個(gè)TCP連接的狀態(tài)進(jìn)行跟蹤,跟蹤信息將會(huì)放在位于內(nèi)核內(nèi)存中的conntrackdatabase中,這個(gè)數(shù)據(jù)庫(kù)的大小有限,當(dāng)系統(tǒng)中存在過(guò)多的TCP連接時(shí),數(shù)據(jù)庫(kù)容量不足,IP_TABLE無(wú)法為新的TCP連接建立跟蹤信息,于是表現(xiàn)為在connect()調(diào)用中阻塞。此時(shí)就必須修改內(nèi)核對(duì)更大跟蹤的TCP連接數(shù)的限制,方法同修改內(nèi)核對(duì)本地端口號(hào)范圍的限制是類(lèi)似的:
之一步,修改/etc/sysctl.conf文件,在文件中添加如下行:
net.ipv4.ip_conntrack_max = 10240
這表明將系統(tǒng)對(duì)更大跟蹤的TCP連接數(shù)限制設(shè)置為10240。請(qǐng)注意,此限制值要盡量小,以節(jié)省對(duì)內(nèi)核內(nèi)存的占用。
第二步,執(zhí)行sysctl命令:
$ sysctl -p
如果系統(tǒng)沒(méi)有錯(cuò)誤提示,就表明系統(tǒng)對(duì)新的更大跟蹤的TCP連接數(shù)限制修改成功。如果按上述參數(shù)進(jìn)行設(shè)置,則理論上單獨(dú)一個(gè)進(jìn)程最多可以同時(shí)建立10000多個(gè)TCP客戶端連接。
3、使用支持高并發(fā)網(wǎng)絡(luò)I/O的編程技術(shù)
在Linux上編寫(xiě)高并發(fā)TCP連接應(yīng)用程序時(shí),必須使用合適的網(wǎng)絡(luò)I/O技術(shù)和I/O事件分派機(jī)制。
可用的I/O技術(shù)有同步I/O,非阻塞式同步I/O(也稱(chēng)反應(yīng)式I/O),以及異步I/O。在高TCP并發(fā)的情形下,如果使用同步I/O,這會(huì)嚴(yán)重阻塞程序的運(yùn)轉(zhuǎn),除非為每個(gè)TCP連接的I/O創(chuàng)建一個(gè)線程。但是,過(guò)多的線程又會(huì)因系統(tǒng)對(duì)線程的調(diào)度造成巨大開(kāi)銷(xiāo)。因此,在高TCP并發(fā)的情形下使用同步I /O 是不可取的,這時(shí)可以考慮使用非阻塞式同步I/O或異步I/O。非阻塞式同步I/O的技術(shù)包括使用select(),poll(),epoll等機(jī)制。異步I/O的技術(shù)就是使用AIO。
從I/O事件分派機(jī)制來(lái)看,使用select()是不合適的,因?yàn)樗С值牟l(fā)連接數(shù)有限(通常在1024個(gè)以內(nèi))。如果考慮性能,poll()也是不合適的,盡管它可以支持的較高的TCP并發(fā)數(shù),但是由于其采用“輪詢”機(jī)制,當(dāng)并發(fā)數(shù)較高時(shí),其運(yùn)行效率相當(dāng)?shù)停⒖赡艽嬖贗/O事件分派不均,導(dǎo)致部分 TCP連接上的I/O出現(xiàn)“饑餓”現(xiàn)象。而如果使用epoll或AIO,則沒(méi)有上述問(wèn)題(早期 Linux內(nèi)核的AIO技術(shù)實(shí)現(xiàn)是通過(guò)在內(nèi)核中為每個(gè)I/O請(qǐng)求創(chuàng)建一個(gè)線程來(lái)實(shí)現(xiàn)的,這種實(shí)現(xiàn)機(jī)制在高并發(fā)TCP連接的情形下使用其實(shí)也有嚴(yán)重的性能問(wèn)題。但在最新的Linux內(nèi)核中,AIO的實(shí)現(xiàn)已經(jīng)得到改進(jìn))。
Linux下 client server 連不上
read是阻塞的,比如你server在read的時(shí)候,帆神server的這個(gè)進(jìn)程就會(huì)阻塞在這里了,你的client也是上來(lái)就read這樣,他也阻塞在這里了,二個(gè)人沒(méi)有人write全read這樣就表現(xiàn)成你代碼的效果了。大體給改了一下,client上來(lái)發(fā)個(gè)hello,然后server回一下,client再把這個(gè)打印。還有,你server的fork部分原來(lái)處理有些問(wèn)題也做了些修改。修改后代碼如下:
server:
#include
#include
#include
#include
#include
#include
#include
#include
#define null 0
#define port 7000
#define backlog 10
void process_server(int s)
{
ssize_t size = 0;
char buffer;
// while(1)
{
size = read(s, buffer, 1024);
if(size == 0) return;
}
sprintf(buffer, “%d bytes altogether\n”, size);
printf(“孝拆buffer:%s\n”,buffer);
write(s, buffer, strlen(buffer) + 1);
}
int main(void)
{
struct sockaddr_in sin;
struct sockaddr_in cin;
int SS;
int SC;
int addrlen = sizeof(struct sockaddr);
pid_t pid;
int err;
SS = socket(AF_INET, SOCK_STREAM, 0);
if(SS 0)
{ //父進(jìn)程繼續(xù)監(jiān)聽(tīng)
close(SC);
} else if (pid == 0) {//子進(jìn)程處理這樣寫(xiě)容易產(chǎn)生僵死態(tài)慎虧進(jìn)程
process_server(SC);
close(SC);
} else {//error
close(SC);
}
}
return 0;
}
client:
#include
#include
#include
#include
#include
#include
#include
#include
#define null 0
#define port 7000
#define backlog 10
void process_client(int s)
{
ssize_t size = 0;
char buffer;
// while(1)
{
// size = read(0, buffer, 1024);
// if(size > 0)
{
// write(s, buffer, size);
write(s,”hello”, sizeof(“hello”));
printf(“write over\n”);
size = read(s, buffer, 1024);
printf(“buffer:%s\n”,buffer);
// write(1, buffer, size);
}
}
}
int main(int argc, char *argv)
{
struct sockaddr_in cin;
int SC;
int err;
close(SC);
SC = socket(AF_INET, SOCK_STREAM, 0);
if(SC
----------------
client:
strace -p 4574
Process 4574 attached – interrupt to quit
read(3, ^C 謹(jǐn)毀
主機(jī)的防火墻是必須關(guān)的。
主機(jī)上使用軟件連接登陸VMWare上的Linux,有兩種方式可以慧舉連接:
(1)橋接方式: 使主機(jī)與Linux的IP在同一個(gè)網(wǎng)段中,就可以了,這樣主機(jī)必須要插上網(wǎng)線。
關(guān)于tcp server linux的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
成都創(chuàng)新互聯(lián)科技有限公司,是一家專(zhuān)注于互聯(lián)網(wǎng)、IDC服務(wù)、應(yīng)用軟件開(kāi)發(fā)、網(wǎng)站建設(shè)推廣的公司,為客戶提供互聯(lián)網(wǎng)基礎(chǔ)服務(wù)!
創(chuàng)新互聯(lián)(www.cdcxhl.com)提供簡(jiǎn)單好用,價(jià)格厚道的香港/美國(guó)云服務(wù)器和獨(dú)立服務(wù)器。創(chuàng)新互聯(lián)成都老牌IDC服務(wù)商,專(zhuān)注四川成都IDC機(jī)房服務(wù)器托管/機(jī)柜租用。為您精選優(yōu)質(zhì)idc數(shù)據(jù)中心機(jī)房租用、服務(wù)器托管、機(jī)柜租賃、大帶寬租用,可選線路電信、移動(dòng)、聯(lián)通等。
新聞名稱(chēng):LinuxTCP服務(wù)器:構(gòu)建高效穩(wěn)定的網(wǎng)絡(luò)通信(tcpserverlinux)
當(dāng)前網(wǎng)址:http://www.dlmjj.cn/article/cohjggs.html


咨詢
建站咨詢
