導航:首頁 > 編程語言 > linux下tcp編程

linux下tcp編程

發布時間:2023-06-16 02:03:37

linux tcp/ip 網路通信編程

/*************************************
文件名:server.c
linux下socket網路編程簡例-服務端程序
伺服器埠設為0x8888(埠和地址可根據實際情況更改,或者使用參數傳入)
伺服器地址設為192.168.1.104
作者:kikilizhm#163.com(將#換為@)
*/
#include<stdlib.h>
#include<sys/types.h>
#include<stdio.h>
#include<sys/socket.h>
#include<linux/in.h>
#include<string.h>
intmain()
{
intsfp,nfp;/*定義兩個描述符*/
structsockaddr_ins_add,c_add;
intsin_size;
unsignedshortportnum=0x8888;/*服務端使用埠*/
printf("Hello,welcometomyserver! ");
sfp=socket(AF_INET,SOCK_STREAM,0);
if(-1==sfp)
{
printf("socketfail! ");
return-1;
}
printf("socketok! ");
/*填充伺服器埠地址信息,以便下面使用此地址和埠監聽*/
bzero(&s_add,sizeof(structsockaddr_in));
s_add.sin_family=AF_INET;
s_add.sin_addr.s_addr=htonl(INADDR_ANY);/*這里地址使用全0,即所有*/
s_add.sin_port=htons(portnum);
/*使用bind進行綁定埠*/
if(-1==bind(sfp,(structsockaddr*)(&s_add),sizeof(structsockaddr)))
{
printf("bindfail! ");
return-1;
}
printf("bindok! ");
/*開始監聽相應的埠*/
if(-1==listen(sfp,5))
{
printf("listenfail! ");
return-1;
}
printf("listenok ");
while(1)
{
sin_size=sizeof(structsockaddr_in);
/*accept服務端使用函數,調用時即進入阻塞狀態,等待用戶進行連接,在沒有客戶端進行連接時,程序停止在此處,
不會看到後面的列印,當有客戶端進行連接時,程序馬上執行一次,然後再次循環到此處繼續等待。
此處accept的第二個參數用於獲取客戶端的埠和地址信息。
*/
nfp=accept(sfp,(structsockaddr*)(&c_add),&sin_size);
if(-1==nfp)
{
printf("acceptfail! ");
return-1;
}
printf("acceptok! Serverstartgetconnectfrom%#x:%#x ",ntohl(c_add.sin_addr.s_addr),ntohs(c_add.sin_port));
/*這里使用write向客戶端發送信息,也可以嘗試使用其他函數實現*/
if(-1==write(nfp,"hello,welcometomyserver ",32))
{
printf("writefail! ");
return-1;
}
printf("writeok! ");
close(nfp);
}
close(sfp);
return0;
}
/*************************************
文件名:client.c
linux下socket網路編程簡例-客戶端程序
伺服器埠設為0x8888(埠和地址可根據實際情況更改,或者使用參數傳入)
伺服器地址設為192.168.1.104
作者:kikilizhm#163.com(將#換為@)
*/
#include<stdlib.h>
#include<sys/types.h>
#include<stdio.h>
#include<sys/socket.h>
#include<linux/in.h>
#include<string.h>
intmain()
{
intcfd;/*文件描述符*/
intrecbytes;
intsin_size;
charbuffer[1024]={0};/*接受緩沖區*/
structsockaddr_ins_add,c_add;/*存儲服務端和本端的ip、埠等信息結構體*/
unsignedshortportnum=0x8888;/*服務端使用的通信埠,可以更改,需和服務端相同*/
printf("Hello,welcometoclient! ");
/*建立socket使用網際網路,TCP流傳輸*/
cfd=socket(AF_INET,SOCK_STREAM,0);
if(-1==cfd)
{
printf("socketfail! ");
return-1;
}
printf("socketok! ");
/*構造伺服器端的ip和埠信息,具體結構體可以查資料*/
bzero(&s_add,sizeof(structsockaddr_in));
s_add.sin_family=AF_INET;
s_add.sin_addr.s_addr=inet_addr("192.168.1.104");/*ip轉換為4位元組整形,使用時需要根據服務端ip進行更改*/
s_add.sin_port=htons(portnum);/*這里htons是將short型數據位元組序由主機型轉換為網路型,其實就是
將2位元組數據的前後兩個位元組倒換,和對應的ntohs效果、實質相同,只不過名字不同。htonl和ntohl是
操作的4位元組整形。將0x12345678變為0x78563412,名字不同,內容兩兩相同,一般情況下網路為大端,
PPC的cpu為大端,x86的cpu為小端,arm的可以配置大小端,需要保證接收時位元組序正確。
*/
printf("s_addr=%#x,port:%#x ",s_add.sin_addr.s_addr,s_add.sin_port);/*這里列印出的是小端
和我們平時看到的是相反的。*/
/*客戶端連接伺服器,參數依次為socket文件描述符,地址信息,地址結構大小*/
if(-1==connect(cfd,(structsockaddr*)(&s_add),sizeof(structsockaddr)))
{
printf("connectfail! ");
return-1;
}
printf("connectok! ");
/*連接成功,從服務端接收字元*/
if(-1==(recbytes=read(cfd,buffer,1024)))
{
printf("readdatafail! ");
return-1;
}
printf("readok REC: ");
buffer[recbytes]='';
printf("%s ",buffer);
getchar();/*此句為使程序暫停在此處,可以使用netstat查看當前的連接*/
close(cfd);/*關閉連接,本次通信完成*/
return0;
}

㈡ 在linux下編制和windows下程序的TCP通信

首先學會使用系統,win不成問題,linux了解基本命令即可,如果你的目標只是上述實現tcp通信,那麼直接在圖形化界面操作即可

然後學習一門編程,java,c++抑或其他,一個即可,socket編程部分好好看看(網路相關)

然後學習網路基本原理,特別不推薦國內教材,你要相信,能給你一瓢水,作者就要有一缸水或者一條河才行,國內教材講解的相對較淺,且多糾結概念,原理方面欠缺。推薦:【COMPUTER NETWORKING (A Top-Down Approach Featuring the Internet)】,中文翻譯【計算機網路,自頂向下方法與internet特色】,英文過關的,強烈建議看英文原版

然後,就是自己動手實踐,慢慢摸索的過程了

話說,實現tcp通信,在windows下完全可以勝任,與平台無關,因為無論是linux,還是windows,採用的都是tcp/ip協議,如果你windows用著順手,何必非要在linux下編制?

㈢ linux tcp編程怎麼增加對數函數

gcc -o test test.c -lm

要連接庫
建議看看《Linux就該這么學》這本書。

㈣ C語言Linux系統下TCP編程,connect 錯誤

你的client有問題,連接之前沒有指定server的ip。
你只指定了埠。
struct sockaddr_in servaddr;
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(HELLO_WORLD_SERVER_PORT);
servaddr.sin_addr.s_addr=inet_addr(serverip);//加上server的ip即可

㈤ 如何在LINUX發送一個tcp請求

這個就需要在 Linux 系統下編寫網路的 TCP/IP socket 程序了。可以分別編寫 server、client 端的代碼。這些在網路編程的教材上都有標準的代碼。

㈥ LINUX網路編程TCP伺服器 客戶端 有亂碼怎麼解決

解決辦法:
1.在客戶端n=read(socketfd,buff,1023);代碼之前加上memset(buff,0,sizeof(buff));,這是保證收到較短數據(使用TCP你不能保證每次接收的數據和發送的數據時等長的),列印也是正確的;
2.將客戶端buff[n+1]+='\0';修改為buff[n]='\0';,這是因為n是下標,已經是最後一個位置了;
3.將伺服器端buff[n+1]+='\0';修改為buff[n]='\0';,這是因為n是下標,已經是最後一個位置了,而且和第2)一樣,那個加號也要去掉,應該是筆誤吧;
4.最大的問題,將伺服器端write(connectfd,buff,1023);,你怎麼能夠保證收到1023個字元呢?也應該將while中條件移出作為WHILE中的一條語句,而且加上前面所述的memset語句,而將這里的write(connectfd,buff,1023);修改為write(connectfd,buff,strlen(buff))。
祝共同進步!

㈦ 暢談linux下TCP(上)

tcp 協議 是互聯網中最常用的協議 , 開發人員基本上天天和它打交道,對它進行深入了解。 可以幫助我們排查定位bug和進行程序優化。下面我將就TCP幾個點做深入的探討

客戶端:收到 ack 後 分配連接資源。 發送數據
伺服器 : 收到 syn 後立即 分配連接資源

客戶端:收到ACK, 立即分配資源
伺服器:收到ACK, 立即分配資源

既然三次握手也不是100%可靠, 那四次,五次,六次。。。呢? 其實都一樣,不管多少次都有丟包問題。

client 只發送一個 SYN, server 分配一個tcb, 放入syn隊列中。 這時候連接叫 半連接 狀態;如果server 收不到 client 的ACK, 會不停重試 發送 ACK-SYN 給client 。重試間隔 為 2 的 N 次方 疊加(2^0 , 2^1, 2^2 ....);直至超時才釋放syn隊列中的這個 TCB;
在半連接狀態下, 一方面會佔用隊列配額資源,另一方面佔用內存資源。我們應該讓半連接狀態存在時間盡可能的小

當client 向一個未打開的埠發起連接請求時,會收到一個RST回復包

當listen 的 backlog 和 somaxconn 都設置了得時候, 取兩者min值

Recv-Q 是accept 隊列當前個數, Send-Q 設置最大值

這種SYN洪水攻擊是一種常見攻擊方式,就是利用半連接隊列特性,占滿syn 隊列的 資源,導致 client無法連接上。
解決方案:

為什麼不像握手那樣合並成三次揮手? 因為和剛開始連接情況,連接是大家都從0開始, 關閉時有歷史包袱的。server(被動關閉方) 收到 client(主動關閉方) 的關閉請求FIN包。 這時候可能還有未發送完的數據,不能丟棄。 所以需要分開。事實可能是這樣

當然,在沒有待發數據,並且允許 Delay ACK 情況下, FIN-ACK合並還是非常常見的事情,這是三次揮手是可以的。

同上

CLOSE_WAIT 是被動關閉方才有的狀態

被動關閉方 [收到 FIN 包 發送 ACK 應答] 到 [發送FIN, 收到ACK ] 期間的狀態為 CLOSE_WAIT, 這個狀態仍然能發送數據。 我們叫做 半關閉 , 下面用個例子來分析:

這個是我實際生產環境碰到的一個問題,長連接會話場景,server端收到client的rpc call 請求1,處理發現請求包有問題,就強制關閉結束這次會話, 但是 因為client 發送 第二次請求之前,並沒有去調用recv,所以並不知道 這個連接被server關閉, 繼續發送 請求2 , 此時是半連接,能夠成功發送到對端機器,但是recv結果後,遇到連接已經關閉錯誤。

如果 client 和 server 恰好同時發起關閉連接。這種情況下,兩邊都是主動連接,都會進入 TIME_WAIT狀態

1、 被動關閉方在LAST_ACK狀態(已經發送FIN),等待主動關閉方的ACK應答,但是 ACK丟掉, 主動方並不知道,以為成功關閉。因為沒有TIME_WAIT等待時間,可以立即創建新的連接, 新的連接發送SYN到前面那個未關閉的被動方,被動方認為是收到錯誤指令,會發送RST。導致創建連接失敗。

2、 主動關閉方斷開連接,如果沒有TIME_WAIT等待時間,可以馬上建立一個新的連接,但是前一個已經斷開連接的,延遲到達的數據包。 被新建的連接接收,如果剛好seq 和 ack欄位 都正確, seq在滑動窗口范圍內(只能說機率非常小,但是還是有可能會發生),會被當成正確數據包接收,導致數據串包。 如果不在window范圍內,則沒有影響( 發送一個確認報文(ack 欄位為期望ack的序列號,seq為當前發送序列號),狀態變保持原樣)

TIME_WAIT 問題比較比較常見,特別是CGI機器,並發量高,大量連接後段服務的tcp短連接。因此也衍生出了多種手段解決。雖然每種方法解決不是那麼完美,但是帶來的好處一般多於壞處。還是在日常工作中會使用。
1、改短TIME_WAIT 等待時間

這個是第一個想到的解決辦法,既然等待時間太長,就改成時間短,快速回收埠。但是實際情況往往不樂觀,對於並發的機器,你改多短才能保證回收速度呢,有時候幾秒鍾就幾萬個連接。太短的話,就會有前面兩種問題小概率發生。

2、禁止Socket lingering

這種情況下關閉連接,會直接拋棄緩沖區中待發送的數據,會發送一個RST給對端,相當於直接拋棄TIME_WAIT, 進入CLOSE狀態。同樣因為取消了 TIME_WAIT 狀態,會有前面兩種問題小概率發生。

3、tcp_tw_reuse
net.ipv4.tcp_tw_reuse選項是 從 TIME_WAIT 狀態的隊列中,選取條件:1、remote 的 ip 和埠相同, 2、選取一個時間戳小於當前時間戳; 用來解決埠不足的尷尬。

現在埠可以復用了,看看如何面對前面TIME_WAIT 那兩種問題。 我們仔細回顧用一下前面兩種問題。 都是在新建連接中收到老連接的包導致的問題 , 那麼如果我能在新連接中識別出此包為非法包,是不是就可以丟掉這些無用包,解決問題呢。

需要實現這些功能,需要擴展一下tcp 包頭。 增加 時間戳欄位。 發送者 在每次發送的時候。 在tcp包頭裡面帶上發送時候的時間戳。 當接收者接收的時候,在ACK應答中除了TCP包頭中帶自己此時發送的時間戳,並且把收到的時間戳附加在後面。也就是說ACK包中有兩個時間戳欄位。結構如下:

那我們接下來一個個分析tcp_tw_reuse是如何解決TIME_WAIT的兩個問題的

4、tcp_tw_recycle

tcp_tw_recycle 也是藉助 timestamp機制。顧名思義, tcp_tw_reuse 是復用 埠,並不會減少 TIME-WAIT 數量。你去查詢機器上TIME-WAIT 數量,還是 幾千幾萬個,這點對有強迫症的同學感覺很不舒服。tcp_tw_recycle 是 提前 回收 TIME-WAIT資源。會減少 機器上 TIME-WAIT 數量。

tcp_tw_recycle 工作原理是。

㈧ LINUX網路編程TCP的伺服器 客戶端 有亂碼怎麼解決

網一科技的代理伺服器正規專業.我朋友推薦我用了效果很好。希望對你有幫助您好!今後一起共勉!更多交流在CSDN,365testing,測評網

閱讀全文

與linux下tcp編程相關的資料

熱點內容
單片機燒錄員 瀏覽:970
美國數據伺服器可以部署什麼業務 瀏覽:973
如何卸載伺服器中的ie 瀏覽:42
單片機必須學編程嗎 瀏覽:153
如何判斷是否與伺服器連接資料庫 瀏覽:740
吃甜食會緩解壓力嘛 瀏覽:317
pdf魔鬼 瀏覽:29
二維數組遞歸解決演算法問題 瀏覽:382
java反射例子 瀏覽:670
惠普筆記本自帶解壓軟體 瀏覽:840
抖音視頻後台壓縮 瀏覽:707
app里的視頻廣告從哪裡接的 瀏覽:556
天翼雲伺服器跟騰訊雲 瀏覽:618
cyk演算法實現 瀏覽:191
大潘號app在哪裡可以下載 瀏覽:109
怎麼做解壓豌豆捏捏樂 瀏覽:618
安卓手機怎麼調成蘋果表情 瀏覽:755
android藍牙聲音 瀏覽:850
橫盤震盪選股公式源碼 瀏覽:589
子平pdf 瀏覽:507