linux網路程式設計(完整版)

2021-10-11 00:26:43 字數 4381 閱讀 7828

之間在網上看到很多網路程式設計都是乙個乙個demo,今天我把之前學到的彙總起來,希望大家可以進行補充。

我理解的網路通訊分為4種

1,udp客戶端

2,udp服務端

3,tcp客戶端

4,tcp服務端

執行緒中我使用過兩種方式程式設計,一種是經典函式式程式設計加上標誌位,如下:

while(1)12

3456

78910

其中各函式裡面放置了大量的標誌位,如下:

void client_init(void)

void sock_send(void)

}void select_handler(void)}1

2345

6789

1011

1213

1415

1617

1819

2021

22這種方式,我覺得在看**的時候很亂,但是他在大量的通訊時還比較友好,可以建立乙個結構體陣列,每個陣列成員代表乙個客戶端,結構體放置client_init_flag和send_flag。

還有一種方式採用的是狀態機程式設計

建立列舉

typedef enum client_statues_t

client_statues_t;

client_statues_t client_statues;12

3456

7while(1)

}123456

78910

1112

1314

1516

狀態機在微控制器使用很常見,但是如果多客戶端初始化與傳送,容易搞混,並且個人覺得增刪查改略費勁,有可能是我自己水平有限,所以今天只寫了乙個關於第一種方式的**。因為標誌位太多了,而且各種判斷比較亂,所以以下就沒有各種標誌位,但真正專案中是要有的並且還需要有列印日誌功能(printf函式),整體思路如下:

建立udp服務端,建立tcp服務端

建立udp客戶端,建立tcp客戶端

傳送資料

接受資料並處理

12

345首先是udp服務端,建立tcp服務端,服務端程式比客戶端較簡單

//返回值為是否成功標誌,需要在各行賦值**中判斷,此**不進行演示

//create_udpserver()、create_tcpserver()引數可以為全域性變數的關於伺服器端的結構體,結構體裡埠號,初始化標誌位,等等,此**不進行演示

struct sockaddr_in udp_sockserver;

void create_udpserver(void)

struct sockaddr_in tcp_sockserver;

void create_tcpserver(void)

void server_init(void)12

3456

78910

1112

1314

1516

1718

1920

2122

2324

2526

2728

29其次是建立tcp和udp的客戶端

//返回值為是否成功標誌,需要在各行賦值**中判斷,此**不進行演示

//create_tcpclient()、create_udpclient(v)引數可以為全域性變數的關於客戶端的結構體,要連線伺服器的結構體資訊,初始化標誌位,等等,此**不進行演示

struct sockaddr_in tcpserver;

void create_tcpclient(void)

/*把connect單獨寫是因為這個步驟比較特殊,他是阻塞函式,需要有一定的延時,有兩種方、法,一種是利用setsockopt:

一種是利用select檢查socket描述符:

*/void tcpclient_connectserver(void)

struct sockaddr_in udpserver;

void create_udpclient(void)

void client_init(void)12

3456

78910

1112

1314

1516

1718

1920

2122

2324

2526

2728

2930

3132

3334

3536

3738

3940

41udp 伺服器接受與傳送函式,這個只設定能接受乙個客戶端發數

//udp先接受客戶端的資料,然後傳送資料

void udp_server_recviveandsend(void)12

3456

7//tcp服務端是最難的,需要考慮客戶端的ip,個數限制,並根據每個客戶端進行通訊,這裡需要設定乙個結構體陣列,

typedef struct tcp_accept_t

tcp_accept_t;

#define num 100//定義最大接受客戶端的數量,

tcp_accept_t tcp_accept[num];12

3456

78910

11tcp接受客戶端大體思路是這樣想的:

1,利用select先獲取accept之前的套接字

2,當accept響應,建立新套接字

3,有了新套接字,利用select獲取receive的響應

4,如果新來客戶端總數超過num,則放棄最早的客戶端

create_tcpserver();

struct sockaddr_in sockclient;

while(1); }

for(int i = 0; i0)

} }

if(fd_isset(tcp_sockserver, &fdsockset)) 

} }

/* ip相同,則不需要關閉任何客戶端 */

for (i = 0; i < socket_accept_max; i++)

} /* 新來裝置,判斷是否num不夠,如果num夠則新增acceptsocket */

for (i = 0; i < socket_accept_max; i++)

} /* 新來裝置,判斷是否num不夠,如果num不夠則新增acceptsocket並放棄最早的客戶端 */

j = 0;

lifenummin = tcpaccept[0].lifenum;

for (i = 1; i < socket_accept_max; i++)

}

accept_new_socket:

if(tcpaccept[j].socket > 0)

tcpaccept[j].socket = newsocket;

tcpaccept[j].ip = ip;

tcpaccept[j].port = port;

tcpaccept[j].status = 0xff; /* socket正常使用 */

tcpaccept[j].lifenum = lifenummax;

}}

}12

3456

78910

1112

1314

1516

1718

1920

2122

2324

2526

2728

2930

3132

3334

3536

3738

3940

4142

4344

4546

4748

4950

5152

5354

5556

5758

5960

6162

6364

6566

6768

6970

7172

7374

7576

7778

7980

8182

8384

8586

8788

8990

9192

9394

9596

9798

99100

101其中放棄最早的客戶端採用了比較簡單的演算法

每個客戶端在連線時給予乙個lifenum生命值,還有乙個不斷增加的計數器 lifenummax,當客戶端增加到最大數量時,比較前幾個客戶端的生命值,把最小的除去,因為它連線的最久。生命值**為

lifenummax++;

if(lifenummax >= 100000000)

} }

mysql完整版 MYSQL安裝(完整版)

一 完全解除安裝mysql yum remove mysql mysql server mysql libs compat mysql51 rm rf var lib mysql rm etc my.cnf 檢視是否還有mysql軟體 rpm qa grep mysql 如果存在的話,繼續刪除即可。...

php完整版,ThinkPHP5 0完整版

thinkphp5.0版本是乙個顛覆和重構版本,官方團隊歷時十月,傾注了大量的時間和精力,採用全新的架構思想,引入了更多的php新特性,優化了核心,減少了依賴,實現了真正的惰性載入,支援composer,並針對api開發做了大量的優化,包括路由 日誌 異常 模型 資料庫 模板引擎和驗證等模組都已經重...

JS完整版原型鏈剖析之完整版

爭對上兩篇遺留的問題建構函式和object建構函式 proto 屬性執行的問題,我們可以分析出最終他們的原型鏈 即物件原型的物件原型 最後肯定會執行null不然就會一直指向下去 建構函式和object建構函式指向的同乙個原型物件 function建構函式的原型物件 而這個原型物件的 proto 屬性...