linuxsocket設置
① linux下setsockopt設置socket超時
she would watch a show and buy some gifts.
② 請問linux怎麼增大socket連接上限
1、修改用戶進程可打開文件數限制
在Linux平台上,無論編寫客戶端程序還是服務端程序,在進行高並發TCP連接處理時,
最高的並發數量都要受到系統對用戶單一進程同時可打開文件數量的限制(這是因為系統
為每個TCP連接都要創建一個socket句柄,每個socket句柄同時也是一個文件句柄)。
可使用ulimit命令查看系統允許當前用戶進程打開的文件數限制:
[speng@as4 ~]$ ulimit -n
1024
這表示當前用戶的每個進程最多允許同時打開1024個文件,這1024個文件中還得除去
每個進程必然打開的標准輸入,標准輸出,標准錯誤,伺服器監聽 socket,
進程間通訊的unix域socket等文件,那麼剩下的可用於客戶端socket連接的文件數就
只有大概1024-10=1014個左右。也就是說預設情況下,基於Linux的通訊程序最多允許
同時1014個TCP並發連接。
對於想支持更高數量的TCP並發連接的通訊處理程序,就必須修改Linux對當前用戶的
進程同時打開的文件數量的軟限制(soft limit)和硬限制(hardlimit)。其中軟限制
是指Linux在當前系統能夠承受的范圍內進一步限制用戶同時打開的文件數;硬限制
則是根據系統硬體資源狀況(主要是系統內存)計算出來的系統最多可同時打開的文件數量。
通常軟限制小於或等於硬限制。
修改上述限制的最簡單的辦法就是使用ulimit命令:
[speng@as4 ~]$ ulimit -n
上述命令中,在中指定要設置的單一進程允許打開的最大文件數。如果系統回顯
類似於「Operation notpermitted」之類的話,說明上述限制修改失敗,實際上是
因為在中指定的數值超過了Linux系統對該用戶打開文件數的軟限制或硬限制。
因此,就需要修改Linux系統對用戶的關於打開文件數的軟限制和硬限制。
第一步,修改/etc/security/limits.conf文件,在文件中添加如下行:
speng soft nofile 10240
speng hard nofile 10240
其中speng指定了要修改哪個用戶的打開文件數限制,可用』*'號表示修改所有用戶的限制;
soft或hard指定要修改軟限制還是硬限制;10240則指定了想要修改的新的限制值,
即最大打開文件數(請注意軟限制值要小於或等於硬限制)。修改完後保存文件。
第二步,修改/etc/pam.d/login文件,在文件中添加如下行:
session required /lib/security/pam_limits.so
這是告訴Linux在用戶完成系統登錄後,應該調用pam_limits.so模塊來設置系統對
該用戶可使用的各種資源數量的最大限制(包括用戶可打開的最大文件數限制),
而pam_limits.so模塊就會從/etc/security/limits.conf文件中讀取配置來設置這些限制值。
修改完後保存此文件。
第三步,查看Linux系統級的最大打開文件數限制,使用如下命令:
[speng@as4 ~]$ cat /proc/sys/fs/file-max
12158
這表明這台Linux系統最多允許同時打開(即包含所有用戶打開文件數總和)12158個文件,
是Linux系統級硬限制,所有用戶級的打開文件數限制都不應超過這個數值。通常這個系統級
硬限制是Linux系統在啟動時根據系統硬體資源狀況計算出來的最佳的最大同時打開文件數限制,
如果沒有特殊需要,不應該修改此限制,除非想為用戶級打開文件數限制設置超過此限制的值。
修改此硬限制的方法是修改/etc/rc.local腳本,在腳本中添加如下行:
echo 22158 > /proc/sys/fs/file-max
這是讓Linux在啟動完成後強行將系統級打開文件數硬限制設置為22158。修改完後保存此文件。
完成上述步驟後重啟系統,一般情況下就可以將Linux系統對指定用戶的單一進程允許同時
打開的最大文件數限制設為指定的數值。如果重啟後用 ulimit-n命令查看用戶可打開文件數限制
仍然低於上述步驟中設置的最大值,這可能是因為在用戶登錄腳本/etc/profile中使用ulimit -n命令
已經將用戶可同時打開的文件數做了限制。由於通過ulimit-n修改系統對用戶可同時打開文件的
最大數限制時,新修改的值只能小於或等於上次 ulimit-n設置的值,因此想用此命令增大這個
限制值是不可能的。
所以,如果有上述問題存在,就只能去打開/etc/profile腳本文件,
在文件中查找是否使用了ulimit-n限制了用戶可同時打開的最大文件數量,如果找到,
則刪除這行命令,或者將其設置的值改為合適的值,然後保存文件,用戶退出並重新登錄系統即可。
通過上述步驟,就為支持高並發TCP連接處理的通訊處理程序解除關於打開文件數量方面的系統限制。
2、修改網路內核對TCP連接的有關限制
在Linux上編寫支持高並發TCP連接的客戶端通訊處理程序時,有時會發現盡管已經解除了系統
對用戶同時打開文件數的限制,但仍會出現並發TCP連接數增加到一定數量時,再也無法成功
建立新的TCP連接的現象。出現這種現在的原因有多種。
第一種原因可能是因為Linux網路內核對本地埠號范圍有限制。此時,進一步分析為什麼無法
建立TCP連接,會發現問題出在connect()調用返回失敗,查看系統錯誤提示消息是「Can』t assign requestedaddress」。同時,如果在此時用tcpmp工具監視網路,會發現根本沒有TCP連接時客戶端
發SYN包的網路流量。這些情況說明問題在於本地Linux系統內核中有限制。
其實,問題的根本原因
在於Linux內核的TCP/IP協議實現模塊對系統中所有的客戶端TCP連接對應的本地埠號的范圍
進行了限制(例如,內核限制本地埠號的范圍為1024~32768之間)。當系統中某一時刻同時
存在太多的TCP客戶端連接時,由於每個TCP客戶端連接都要佔用一個唯一的本地埠號
(此埠號在系統的本地埠號范圍限制中),如果現有的TCP客戶端連接已將所有的本地埠號占滿,
則此時就無法為新的TCP客戶端連接分配一個本地埠號了,因此系統會在這種情況下在connect()
調用中返回失敗,並將錯誤提示消息設為「Can』t assignrequested address」。
有關這些控制
邏輯可以查看Linux內核源代碼,以linux2.6內核為例,可以查看tcp_ipv4.c文件中如下函數:
static int tcp_v4_hash_connect(struct sock *sk)
請注意上述函數中對變數sysctl_local_port_range的訪問控制。變數sysctl_local_port_range
的初始化則是在tcp.c文件中的如下函數中設置:
void __init tcp_init(void)
內核編譯時默認設置的本地埠號范圍可能太小,因此需要修改此本地埠范圍限制。
第一步,修改/etc/sysctl.conf文件,在文件中添加如下行:
net.ipv4.ip_local_port_range = 1024 65000
這表明將系統對本地埠范圍限制設置為1024~65000之間。請注意,本地埠范圍的最小值
必須大於或等於1024;而埠范圍的最大值則應小於或等於65535。修改完後保存此文件。
第二步,執行sysctl命令:
[speng@as4 ~]$ sysctl -p
如果系統沒有錯誤提示,就表明新的本地埠范圍設置成功。如果按上述埠范圍進行設置,
則理論上單獨一個進程最多可以同時建立60000多個TCP客戶端連接。
第二種無法建立TCP連接的原因可能是因為Linux網路內核的IP_TABLE防火牆對最大跟蹤的TCP
連接數有限制。此時程序會表現為在 connect()調用中阻塞,如同死機,如果用tcpmp工具監視網路,
也會發現根本沒有TCP連接時客戶端發SYN包的網路流量。由於 IP_TABLE防火牆在內核中會對
每個TCP連接的狀態進行跟蹤,跟蹤信息將會放在位於內核內存中的conntrackdatabase中,
這個資料庫的大小有限,當系統中存在過多的TCP連接時,資料庫容量不足,IP_TABLE無法為
新的TCP連接建立跟蹤信息,於是表現為在connect()調用中阻塞。此時就必須修改內核對最大跟蹤
的TCP連接數的限制,方法同修改內核對本地埠號范圍的限制是類似的:
第一步,修改/etc/sysctl.conf文件,在文件中添加如下行:
net.ipv4.ip_conntrack_max = 10240
這表明將系統對最大跟蹤的TCP連接數限制設置為10240。請注意,此限制值要盡量小,
以節省對內核內存的佔用。
第二步,執行sysctl命令:
[speng@as4 ~]$ sysctl -p
如果系統沒有錯誤提示,就表明系統對新的最大跟蹤的TCP連接數限制修改成功。
如果按上述參數進行設置,則理論上單獨一個進程最多可以同時建立10000多個TCP客戶端連接。
3、使用支持高並發網路I/O的編程技術
在Linux上編寫高並發TCP連接應用程序時,必須使用合適的網路I/O技術和I/O事件分派機制。
可用的I/O技術有同步I/O,非阻塞式同步I/O(也稱反應式I/O),以及非同步I/O。在高TCP並發的情形下,
如果使用同步I/O,這會嚴重阻塞程序的運轉,除非為每個TCP連接的I/O創建一個線程。
但是,過多的線程又會因系統對線程的調度造成巨大開銷。因此,在高TCP並發的情形下使用
同步 I/O是不可取的,這時可以考慮使用非阻塞式同步I/O或非同步I/O。非阻塞式同步I/O的技術包括使用select(),poll(),epoll等機制。非同步I/O的技術就是使用AIO。
從I/O事件分派機制來看,使用select()是不合適的,因為它所支持的並發連接數有限(通常在1024個以內)。
如果考慮性能,poll()也是不合適的,盡管它可以支持的較高的TCP並發數,但是由於其採用
「輪詢」機制,當並發數較高時,其運行效率相當低,並可能存在I/O事件分派不均,導致部分TCP
連接上的I/O出現「飢餓」現象。而如果使用epoll或AIO,則沒有上述問題(早期Linux內核的AIO技術
實現是通過在內核中為每個 I/O請求創建一個線程來實現的,這種實現機制在高並發TCP連接的情形下
使用其實也有嚴重的性能問題。但在最新的Linux內核中,AIO的實現已經得到改進)。
綜上所述,在開發支持高並發TCP連接的Linux應用程序時,應盡量使用epoll或AIO技術來實現並發的
TCP連接上的I/O控制,這將為提升程序對高並發TCP連接的支持提供有效的I/O保證。
內核參數sysctl.conf的優化
/etc/sysctl.conf 是用來控制linux網路的配置文件,對於依賴網路的程序(如web伺服器和cache伺服器)
非常重要,RHEL默認提供的最好調整。
推薦配置(把原/etc/sysctl.conf內容清掉,把下面內容復制進去):
net.ipv4.ip_local_port_range = 1024 65536
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_sack = 0
net.core.netdev_max_backlog = 30000
net.ipv4.tcp_no_metrics_save=1
net.core.somaxconn = 262144
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
這個配置參考於cache伺服器varnish的推薦配置和SunOne 伺服器系統優化的推薦配置。
varnish調優推薦配置的地址為:http://varnish.projects.linpro.no/wiki/Performance
不過varnish推薦的配置是有問題的,實際運行表明「net.ipv4.tcp_fin_timeout = 3」的配置
會導致頁面經常打不開;並且當網友使用的是IE6瀏覽器時,訪問網站一段時間後,所有網頁都會
打不開,重啟瀏覽器後正常。可能是國外的網速快吧,我們國情決定需要
調整「net.ipv4.tcp_fin_timeout = 10」,在10s的情況下,一切正常(實際運行結論)。
修改完畢後,執行:
/sbin/sysctl -p /etc/sysctl.conf
/sbin/sysctl -w net.ipv4.route.flush=1
命令生效。為了保險起見,也可以reboot系統。
調整文件數:
linux系統優化完網路必須調高系統允許打開的文件數才能支持大的並發,默認1024是遠遠不夠的。
執行命令:
Shell代碼
echo ulimit -HSn 65536 >> /etc/rc.local
echo ulimit -HSn 65536 >>/root/.bash_profile
ulimit -HSn 65536
③ linux虛擬機進行socket通信要如何設置
請終端下輸入
sudo netstat -a
如果看到了,如果能看到很多unix的鏈接流。則證明linux系統本身已經啟用了很多socket通信。已經是設置好的。
至於如何進行socket通信編程。請尋找相關資料自學。
如果你只是想建立到遠端伺服器的一個ip隧道。架設加密代理的隧道,那麼請告知你使用的linux版本,以及使用的軟體。
④ 在Linux系統中,是否可以設置某個socket鏈接成功建立後在一定的時間內沒有數據通信就把這個鏈
原因:
1、
因為伺服器是時時在監聽有沒有客戶端的連接,如果伺服器不綁定IP和埠的話,客戶端上線的時候怎麼連到伺服器呢,所以伺服器要綁定IP和埠,而客戶端就不需要了,客戶端上線是主動向伺服器發出請求的,因為伺服器已經綁定了IP和埠,所以客戶端上線的就向這個IP和埠發出請求,這時因為客戶開始發數據了(發上線請求),系統就給客戶端分配一個隨機埠,這個埠和客戶端的IP會隨著上線請求一起發給伺服器,服務收到上線請求後就可以從中獲起發此請求的客戶的IP和埠,接下來伺服器就可以利用獲起的IP和埠給客戶端回應消息了。
2、採用UDP通信
1)若有客戶端和伺服器之分的程序,創建sock後即可在該socket上用recvfrom/sendto方法發送接受數據了,因為客戶端只需要用sendto發送數據到指定的地址,當然若是bind了,程序也沒什麼問題,區別就是系統用默認自動bind()指定你自己的socket參數地址(特別是在指定特定埠的UDP對等通信)只是這種情況沒有這樣用的。
那UDP伺服器是怎麼知道客戶端的IP地址和UDP埠?
一般來說有兩種方式:
一種是客戶端發消息顯式地告訴伺服器IP地址和埠,消息內容就包括IP地址和UDP埠。
另外一種就是隱式的,伺服器從收到的包的頭部中得到包的源IP地址和埠。
2)若是沒有客戶端和伺服器之分的程序,即自己指定特定埠的UDP對等通信,則客戶端和伺服器都需要bind()IP地址和埠了。
通常udp服務端根本不需要知道客戶端的socket,它直接建立一個socket用於發送即可,udp通信的關鍵只在於IP和埠。
多個客戶端如果需要點到點分發,必須給服務端socket循環設置每個客戶端的IP並發出,但更常用的是廣播分發,服務端socket設定一個X.X.X.255的廣播地址並始終向它發送,每個客戶端建立的socket只需要綁定這個廣播地址便可以收到。
客戶端用不用bind 的區別
無連接的socket的客戶端和服務端以及面向連接socket的服務端通過調用bind函數來配置本地信息。使用bind函數時,通過將my_addr.sin_port置為0,函數會自動為你選擇一個未佔用的埠來使用。
Bind()函數在成功被調用時返回0;出現錯誤時返回"-1"並將errno置為相應的錯誤號。需要注意的是,在調用bind函數時一般不要將埠號置為小於1024的值,因為1到1024是保留埠號,你可以選擇大於1024中的任何一個沒有被佔用的埠號。
有連接的socket客戶端通過調用Connect函數在socket數據結構中保存本地和遠端信息,無須調用bind(),因為這種情況下只需知道目的機器的IP地址,而客戶通過哪個埠與伺服器建立連接並不需要關心,socket執行體為你的程序自動選擇一個未被佔用的埠,並通知你的程序數據什麼時候打開埠。(當然也有特殊情況,linux系統中rlogin命令應當調用bind函數綁定一個未用的保留埠號,還有當客戶端需要用指定的網路設備介面和埠號進行通信等等)
總之:
1.需要在建連前就知道埠的話,需要 bind
2.需要通過指定的埠來通訊的話,需要 bind
具體到上面那兩個程序,本來用的是TCP,客戶端就不用綁定埠了,綁定之後只能運行一個client 的程序,是屬於自己程序中人為設定的障礙,而從伺服器那邊得到的客戶機連接埠號(是系統自動分配的)與這邊客戶機綁定的埠號根本是不相關的,所以客戶 綁定也就失去了意義。
注意:
一個埠可以用於多個連接(比如多個客戶端連接伺服器的同一埠)。但是在同一個操作系統上,即伺服器和客戶端都是本機上,多個客戶端去連接伺服器,只有第一個客戶端的連接會被接收,第二個客戶端的連接請求不會被接收。
首先,伺服器和客戶端都可以bind,bind並不是伺服器的專利。
客戶端進程bind埠: 由進程選擇一個埠去連伺服器,(如果默認情況下,調用bind函數時,內核指定的埠是同一個,那麼運行多個調用了bind 的client 程序,會出現埠被佔用的錯誤)注意這里的埠是客戶端的埠。如果不分配就表示交給內核去選擇一個可用埠。
客戶端進程bind IP地址:相當於為發送出去的IP數據報分配了源IP地址,但交給進程分配IP地址的時候(就是這樣寫明了bind IP地址的時候)這個IP地址必須是主機的一個介面,不能分配一個不存在的IP。如果不分配就表示由內核根據所用的輸出介面來選擇源IP地址。
一般情況下客戶端是不用調用bind函數的,一切都交給內核搞定!
服務端進程bind埠:基本是必須要做的事情,比如一個伺服器啟動時(比如freebsd),它會一個一個的捆綁眾所周知的埠來提供服務,同樣,如果bind了一個埠就表示我這個伺服器會在這個埠提供一些「特殊服務」。
服務端進程bind IP地址:目的是限制了服務端進程創建的socket只接受那些目的地為此IP地址的客戶鏈接,一般一個伺服器程序里都有
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 只是針對IP4,IP6代碼不太一樣
這樣一句話,意思就是:我不指定客戶端的IP,隨便連,來者不拒!
總之只要你bind時候沒有指定哪一項(置為0),內核會幫你選擇。
⑤ linux socket編程 怎麼設置pus
是你的ORACLE_SID,/u01/proct/10.2.0/db_1是ORACLE_HOME,這里需要把N改為Y, 即orcl:/u01/proct/10.2.0/db_1:Y這樣。
2)、以oracle編輯$ORACLE_HOME/bin/dbstart,找到其中第78行:ORACLE_HOME_LISTNER=改為你自己的路徑,或者可以改成ORACLE_HOME_LISTNER=$ORACLE_HOME
保存腳本,以oracle用戶運行dbshut和dbstart看是否能關閉、啟動資料庫。如果不能,一般是參數設置,根據報錯找到對應位置更改。
經過上一步的配置,可以直接用dbstart命令啟動數據listener、instance、asm instances,但是還沒有啟動oracle10g的EM,ORACLE利用web頁面管理資料庫相當方便,也是10g的一個特色,所以應該一並啟動起該服務來。
$ORACLE_HOME/
⑥ linux下創建socket時如何實現指定網口
原理上只有 raw_socket 應該設置網口,正常的 socket 會根據路由來選擇出口。
如果需要指定網口,需要設置 SO_BINDTODEVICE,步驟如下:
填寫結構體 struct ifreq ifr 的 ifr.ifr_name 為指定的網口,如 "eth1"
setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr))
另外,如果只是需要進行測試,不防直接構包,用 libpcap 等庫來進行發送。而不要用系統的 socket 庫來發送。
⑦ 我想請教LINUX 下socket 超時設置的問題
舉例:
s=socket();
設置s為non-blocking;
connect(s,..);
FD_SET...;
rc = select(..., 10s);
if (rc == 0) 表示10s超時了。
這個超時的意思是:10s之內,select中所有socket的事件均未產生(如果至少有一個產生,則rc大於0)
注意:這個10s跟connect本身的超時機制完全無關,前者的設置不影響後者。10s後select的返回,表明10s內connect還沒成功,connect可能還在按自己的超時機制(例如慢啟動)嘗試重連(當然它最終也有個超時)。
至於connect本身的超時是否可以設置,可能各系統不一樣。
順便提醒:connect的socket必須是non-blocking類型,否則,connect會阻塞,也就沒必要用select來檢測是否連接成功。另外,那個s要注冊到write類型的fd中,即select的第3個參數中。
其他listen,recv什麼的,完全類似(但listen,recv本身沒有什麼超時概念)。只不過listen的和recv的socket,要注冊到read的fd中。
⑧ 如何設置linux socket為非阻塞
int flags = fcntl(socket, F_GETFL, 0);
fcntl(socket, F_SETFL, flags | O_NONBLOCK);
⑨ linux下怎麼設置tcp
Socket的send函數在執行時報EAGAIN的錯誤 當客戶通過Socket提供的send函數發送大的數據包時,就可能返回一個EGGAIN的錯誤。該錯誤產生的原因是由於send 函數中的size變數大小超過了tcp_sendspace的值。tcp_sendspace定義了應用在調用send之前能夠在kernel中緩存的數據量。當應用程序在socket中設置了O_NDELAY或者O_NONBLOCK屬性後,如果發送緩存被占滿,send就會返回EAGAIN的錯誤。 為了消除該錯誤,有三種方法可以選擇: 1.調大tcp_sendspace,使之大於send中的size參數 ---no -p -o tcp_sendspace=65536 2.在調用send前,在setsockopt函數中為SNDBUF設置更大的值 3.使用write替代send,因為write沒有設置O_NDELAY或者O_NONBLOCK 1. tcp 收發緩沖區默認值 [root@qljt core]# cat /proc/sys/net/ipv4/tcp_rmem 4096 87380 4161536 87380 :tcp接收緩沖區的默認值 [root@qljt core]# cat /proc/sys/net/ipv4/tcp_wmem 4096 16384 4161536 16384 : tcp 發送緩沖區的默認值 2. tcp 或udp收發緩沖區最大值 [root@qljt core]# cat /proc/sys/net/core/rmem_max 131071 131071:tcp 或 udp 接收緩沖區最大可設置值的一半。 也就是說調用 setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen); 時rcv_size 如果超過 131071,那麼 getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen); 去到的值就等於 131071 * 2 = 262142 [root@qljt core]# cat /proc/sys/net/core/wmem_max 131071 131071:tcp 或 udp 發送緩沖區最大可設置值得一半。 跟上面同一個道理 3. udp收發緩沖區默認值 [root@qljt core]# cat /proc/sys/net/core/rmem_default 111616:udp接收緩沖區的默認值 [root@qljt core]# cat /proc/sys/net/core/wmem_default 111616 111616:udp發送緩沖區的默認值 . tcp 或udp收發緩沖區最小值 tcp 或udp接收緩沖區的最小值為 256 bytes,由內核的宏決定; tcp 或udp發送緩沖區的最小值為 2048 bytes,由內核的宏決定 setsockopt設置socket狀態 1.closesocket(一般不會立即關閉而經歷TIME_WAIT的過程)後想繼續重用該socket: BOOL bReuseaddr=TRUE; setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL)); 2. 如果要已經處於連接狀態的soket在調用closesocket後強制關閉,不經歷TIME_WAIT的過程: BOOL bDontLinger = FALSE; setsockopt(s,SOL_SOCKET,SO_DONTLINGER,(const char*)&bDontLinger,sizeof(BOOL)); 3.在send(),recv()過程中有時由於網路狀況等原因,發收不能預期進行,而設置收發時限: int nNetTimeout=1000;//1秒 //發送時限 setsockopt(socket,SOL_S0CKET,SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int)); //接收時限 setsockopt(socket,SOL_S0CKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int)); 4.在send()的時候,返回的是實際發送出去的位元組(同步)或發送到socket緩沖區的位元組(非同步);系統默認的狀態發送和接收一次為8688位元組(約為8.5K);在實際的過程中發送數據 和接收數據量比較大,可以設置socket緩沖區,而避免了send(),recv()不斷的循環收發: // 接收緩沖區 int nRecvBuf=32*1024;//設置為32K setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int)); //發送緩沖區 int nSendBuf=32*1024;//設置為32K setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int)); 5. 如果在發送數據的時,希望不經歷由系統緩沖區到socket緩沖區的拷貝而影響程序的性能: int nZero=0; setsockopt(socket,SOL_S0CKET,SO_SNDBUF,(char *)&nZero,sizeof(nZero)); 6.同上在recv()完成上述功能(默認情況是將socket緩沖區的內容拷貝到系統緩沖區): int nZero=0; setsockopt(socket,SOL_S0CKET,SO_RCVBUF,(char *)&nZero,sizeof(int)); 7.一般在發送UDP數據報的時候,希望該socket發送的數據具有廣播特性: BOOL bBroadcast=TRUE; setsockopt(s,SOL_SOCKET,SO_BROADCAST,(const char*)&bBroadcast,sizeof(BOOL)); 8.在client連接伺服器過程中,如果處於非阻塞模式下的socket在connect()的過程中可以設置connect()延時,直到accpet()被呼叫(本函數設置只有在非阻塞的過程中有顯著的 作用,在阻塞的函數調用中作用不大) BOOL bConditionalAccept=TRUE; setsockopt(s,SOL_SOCKET,SO_CONDITIONAL_ACCEPT,(const char*)&bConditionalAccept,sizeof(BOOL)); 9.如果在發送數據的過程中(send()沒有完成,還有數據沒發送)而調用了closesocket(),以前我們一般採取的措施是"從容關閉"shutdown(s,SD_BOTH),但是數據是肯定丟失了,如何設置讓程序滿足具體應用的要求(即讓沒發完的數據發送出去後在關閉socket)? struct linger { u_short l_onoff; u_short l_linger; }; linger m_sLinger; m_sLinger.l_onoff=1;//(在closesocket()調用,但是還有數據沒發送完畢的時候容許逗留) // 如果m_sLinger.l_onoff=0;則功能和2.)作用相同; m_sLinger.l_linger=5;//(容許逗留的時間為5秒) setsockopt(s,SOL_SOCKET,SO_LINGER,(const char*)&m_sLinger,sizeof(linger)); 設置套介面的選項。 #include <winsock.h> int PASCAL FAR setsockopt( SOCKET s, int level, int optname, const char FAR* optval, int optlen); s:標識一個套介面的描述字。 level:選項定義的層次;目前僅支持SOL_SOCKET和IPPROTO_TCP層次。 optname:需設置的選項。 optval:指針,指向存放選項值的緩沖區。 optlen:optval緩沖區的長度。 注釋: setsockopt()函數用於任意類型、任意狀態套介面的設置選項值。盡管在不同協議層上存在選項,但本函數僅定義了最高的「套介面」層次上的選項。選項影響套介面的操作,諸如加急數據是否在普通數據流中接收,廣播數據是否可以從套介面發送等等。 有兩種套介面的選項:一種是布爾型選項,允許或禁止一種特性;另一種是整形或結構選項。允許一個布爾型選項,則將optval指向非零整形數;禁止一個選項optval指向一個等於零的整形數。對於布爾型選項,optlen應等於sizeof(int);對其他選項,optval指向包含所需選項的整形數或結構,而optlen則為整形數或結構的長度。SO_LINGER選項用於控制下述情況的行動:套介面上有排隊的待發送數據,且 closesocket()調用已執行。參見closesocket()函數中關於SO_LINGER選項對closesocket()語義的影響。應用程序通過創建一個linger結構來設置相應的操作特性: struct linger { int l_onoff; int l_linger; }; 為了允許SO_LINGER,應用程序應將l_onoff設為非零,將l_linger設為零或需要的超時值(以秒為單位),然後調用setsockopt()。為了允許SO_DONTLINGER(亦即禁止SO_LINGER),l_onoff應設為零,然後調用setsockopt()。 預設條件下,一個套介面不能與一個已在使用中的本地地址捆綁(參見bind())。但有時會需要「重用」地址。因為每一個連接都由本地地址和遠端地址的組合唯一確定,所以只要遠端地址不同,兩個套介面與一個地址捆綁並無大礙。為了通知WINDOWS套介面實現不要因為一個地址已被一個套介面使用就不讓它與另一個套介面捆綁,應用程序可在bind()調用前先設置SO_REUSEADDR選項。請注意僅在bind()調用時該選項才被解釋;故此無需(但也無害)將一個不會共用地址的套介面設置該選項,或者在bind()對這個或其他套介面無影響情況下設置或清除這一選項。 一個應用程序可以通過打開SO_KEEPALIVE選項,使得WINDOWS套介面實現在TCP連接情況下允許使用「保持活動」包。一個WINDOWS套介面實現並不是必需支持「保持活動」,但是如果支持的話,具體的語義將與實現有關,應遵守RFC1122「Internet主機要求-通訊層」中第 4.2.3.6節的規范。如果有關連接由於「保持活動」而失效,則進行中的任何對該套介面的調用都將以WSAENETRESET錯誤返回,後續的任何調用將以WSAENOTCONN錯誤返回。 TCP_NODELAY選項禁止Nagle演算法。Nagle演算法通過將未確認的數據存入緩沖區直到蓄足一個包一起發送的方法,來減少主機發送的零碎小數據包的數目。但對於某些應用來說,這種演算法將降低系統性能。所以TCP_NODELAY可用來將此演算法關閉。應用程序編寫者只有在確切了解它的效果並確實需要的情況下,才設置TCP_NODELAY選項,因為設置後對網路性能有明顯的負面影響。TCP_NODELAY是唯一使用IPPROTO_TCP層的選項,其他所有選項都使用SOL_SOCKET層。 如果設置了SO_DEBUG選項,WINDOWS套介面供應商被鼓勵(但不是必需)提供輸出相應的調試信息。但產生調試信息的機制以及調試信息的形式已超出本規范的討論范圍。 setsockopt()支持下列選項。其中「類型」表明optval所指數據的類型。 選項 類型 意義 SO_BROADCAST BOOL 允許套介面傳送廣播信息。 SO_DEBUG BOOL 記錄調試信息。 SO_DONTLINER BOOL 不要因為數據未發送就阻塞關閉操作。設置本選項相當於將SO_LINGER的l_onoff元素置為零。 SO_DONTROUTE BOOL 禁止選徑;直接傳送。 SO_KEEPALIVE BOOL 發送「保持活動」包。 SO_LINGER struct linger FAR* 如關閉時有未發送數據,則逗留。 SO_OOBINLINE BOOL 在常規數據流中接收帶外數據。 SO_RCVBUF int 為接收確定緩沖區大小。 SO_REUSEADDR BOOL 允許套介面和一個已在使用中的地址捆綁(參見bind())。 SO_SNDBUF int 指定發送緩沖區大小。 TCP_NODELAY BOOL 禁止發送合並的Nagle演算法。 setsockopt()不支持的BSD選項有: 選項名 類型 意義 SO_ACCEPTCONN BOOL 套介面在監聽。 SO_ERROR int 獲取錯誤狀態並清除。 SO_RCVLOWAT int 接收低級水印。 SO_RCVTIMEO int 接收超時。 SO_SNDLOWAT int 發送低級水印。 SO_SNDTIMEO int 發送超時。 SO_TYPE int 套介面類型。 IP_OPTIONS 在IP頭中設置選項。 返回值: 若無錯誤發生,setsockopt()返回0。否則的話,返回SOCKET_ERROR錯誤,應用程序可通過WSAGetLastError()獲取相應錯誤代碼。 錯誤代碼: WSANOTINITIALISED:在使用此API之前應首先成功地調用WSAStartup()。 WSAENETDOWN:WINDOWS套介面實現檢測到網路子系統失效。 WSAEFAULT:optval不是進程地址空間中的一個有效部分。 WSAEINPROGRESS:一個阻塞的WINDOWS套介面調用正在運行中。 WSAEINVAL:level值非法,或optval中的信息非法。 WSAENETRESET:當SO_KEEPALIVE設置後連接超時。 WSAENOPROTOOPT:未知或不支持選項。其中,SOCK_STREAM類型的套介面不支持SO_BROADCAST選項,SOCK_DGRAM 類型的套介面不支持SO_DONTLINGER 、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE選項。 WSAENOTCONN:當設置SO_KEEPALIVE後連接被復位。 WSAENOTSOCK:描述字不是一個套介面。
⑩ 在哪個LINUX版本下,可以設置SOCKET使用 TCP
都可以,這根版本無關