【摘要】 介紹Linux下網(wǎng)絡(luò)編程、線程編程,select機(jī)制,利用子線程響應(yīng)TCP服務(wù)器的請求。
??TCP服務(wù)器創(chuàng)建流程:
1.?創(chuàng)建套接字
2.?綁定IP地址和端口號(創(chuàng)建服務(wù)器)
3.?設(shè)置監(jiān)聽的數(shù)量(限制最大可以連接的客戶端數(shù)量)
4.?等待客戶端連接
5.?實現(xiàn)基本通信
??TCP客戶端創(chuàng)建流程
1.?創(chuàng)建套接字
2.?連接服務(wù)器
3.?實現(xiàn)基本通信
任務(wù)1:網(wǎng)絡(luò)編程
練習(xí):
1.?實現(xiàn)TCP服務(wù)器與TCP客戶端之間的基本通信,收發(fā)數(shù)據(jù) (按照上課的思路流程看函數(shù)文檔)
2.?實現(xiàn)TCP服務(wù)器與TCP客戶端之間的文件傳輸。(單個文件傳輸)
驗證方式:(1) 同一臺電腦演示 (2)同桌之間演示
考慮的問題:
(1)?網(wǎng)絡(luò)的傳輸環(huán)境,考慮應(yīng)答問題
(2)?數(shù)據(jù)丟包之后如何處理? 可以重發(fā)
(3)?超時處理
(4)?服務(wù)器與客戶端之間連接斷開處理。(客戶端和服務(wù)器兩邊都需要重新連接)
文件傳輸可以在廣告機(jī)中使用。
(擴(kuò)展要求): 顯示接收進(jìn)度百分比,顯示接收的文件名稱,推薦: 定義結(jié)構(gòu)體(使用數(shù)據(jù)結(jié)構(gòu))
3.?(擴(kuò)展)實現(xiàn)TCP服務(wù)器與TCP客戶端之間的目錄傳輸。
4.?(擴(kuò)展)實現(xiàn)網(wǎng)絡(luò)聊天室(模仿QQ發(fā)送消息的效果)
??一般情況下,推薦最大每次傳輸?shù)淖止?jié)數(shù)不超過1024字節(jié)。
任務(wù)2:線程編程
#include int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); Compile and link with -pthread. -lpthread |
理解: 一個線程就是一個while(1)。
[root@wbyq linux-share-dir]# gcc app.c /tmp/cccOs4TK.o: In function `main': app.c:(.text+0x69): undefined reference to `pthread_create' app.c:(.text+0x8d): undefined reference to `pthread_create' collect2: ld 返回 1 [root@wbyq linux-share-dir]# gcc app.c -lpthread |
練習(xí):
1.?學(xué)習(xí)線程的基本使用
#include
#include
void *start_1(void *arg)
{
while(1)
{
printf("123\n");
sleep(1);
}
}
void *start_2(void *arg)
{
while(1)
{
printf("456\n");
sleep(1);
}
}
int main(int argc,char *argv[])
{
pthread_t thread_1;
pthread_t thread_2;
pthread_create(&thread_1,NULL,start_1,NULL);
pthread_create(&thread_2,NULL,start_2,NULL);
while(1)
{
printf("789\n");
sleep(1);
}
return 0;
}
2.?實現(xiàn)一個服務(wù)器實現(xiàn)多個客戶端的連接,實現(xiàn)通信。
思路: 一個客戶端就是一個獨立的線程。
3.?擴(kuò)展練習(xí): 實現(xiàn)服務(wù)器同時對多個客戶端進(jìn)行文件發(fā)送。
(1)?服務(wù)器連接上一個客戶端就創(chuàng)建一個線程。
(2)?線程的函數(shù)需要寫幾個? 1個
1個函數(shù)需要考慮的問題: 函數(shù)的可重入性能!
需要考慮到資源搶占! 使用信號量!
(搶答器)
設(shè)置線程分離屬性:
#include
#include
char str1[]="123456";
char str2[]="abcdef";
void *start_1(void *arg)
{
printf("arg1=%s\n",arg);
sleep(1);
}
void *start_2(void *arg)
{
printf("arg2=%s\n",arg);
sleep(2);
}
int main(int argc,char *argv[])
{
pthread_t thread_1;
pthread_t thread_2;
pthread_create(&thread_1,NULL,start_1,"線程1的參數(shù)傳遞測試");
pthread_create(&thread_2,NULL,start_2,"線程2的參數(shù)傳遞測試");
pthread_detach(thread_1); //設(shè)置線程的分離屬性
pthread_detach(thread_2); //設(shè)置線程的分離屬性
while(1)
{
}
return 0;
}
任務(wù)3: select阻塞輪詢機(jī)制
(1)?服務(wù)器什么時候收到數(shù)據(jù)? read
(2)?客戶端什么時候收到數(shù)據(jù)? Read
(3)?客戶端如何判斷已經(jīng)與服務(wù)器斷開連接?
使用select機(jī)制 ,當(dāng)select函數(shù)返回值為1,read函數(shù)為0就表示斷開
(4)?服務(wù)器如何檢測客戶端已經(jīng)斷開連接?
采用心跳包的模式: 規(guī)定客戶端每5秒鐘發(fā)送一個特定的數(shù)據(jù)給服務(wù)器。
??IO 多路復(fù)用是指內(nèi)核一旦發(fā)現(xiàn)進(jìn)程指定的一個或者多個 IO 條件準(zhǔn)備讀取,它就通知該進(jìn)程。
IO 條件:
(1)?網(wǎng)絡(luò)編程中的讀寫
(2)?標(biāo)準(zhǔn)輸出輸入中的讀寫
#include
#include
#include
#include
select:同時可以監(jiān)控多個文件描述符。
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
參數(shù):
int nfds :最大的文件描述符+1
fd_set *readfds :讀事件發(fā)生
fd_set *writefds :寫事件發(fā)生
fd_set *exceptfds:出現(xiàn)問題
struct timeval *timeout:輪詢的時間。
填NULL表示無限阻塞。
結(jié)構(gòu)體里的成員填0,表示不阻塞
結(jié)構(gòu)體里的成員填>0,正常的阻塞時間
返回值: 0表示沒有任何事件發(fā)生,負(fù)數(shù)表示失敗。>0表示發(fā)生對應(yīng)的事件。
void FD_CLR(int fd, fd_set *set); //清除指定文件描述符
int FD_ISSET(int fd, fd_set *set); //檢測指定的文件描述符是否發(fā)生了事件
void FD_SET(int fd, fd_set *set); //添加指定的文件描述符到fd描述符集合(多次調(diào)用)
void FD_ZERO(fd_set *set); //清除整個文件描述符集合
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
TCP服務(wù)器端處理:
#include
#include /* See NOTES */
#include
#include //使用大小端轉(zhuǎn)換函數(shù)
#include
#include
#include
#include
#include
#include
//函數(shù)聲明
void *start_routine_1(void *dev);
void *start_routine_2(void *dev);
typedef void *(*start_routine) (void *);
start_routine fun[]={start_routine_1,start_routine_2};
pthread_t thread_id[2]; //存放線程的標(biāo)識符
int clientfd[2]; //保存TCP客戶端的網(wǎng)絡(luò)套接字
struct sockaddr_in client_address[2]; //存放客戶端的信息
socklen_t address_len[2]; //存放客戶端結(jié)構(gòu)體信息的長度
/*服務(wù)器端口號定義*/
#define P_host 8080
/*TCP服務(wù)器代碼*/
int main(int argc,char *argv[])
{
int socketfd;
struct sockaddr_in server_address; //存放服務(wù)器的IP地址信息
memset(&server_address,0,sizeof(struct sockaddr_in)); //初始化內(nèi)存空間
memset(client_address,0,sizeof(struct sockaddr_in)*2); //初始化內(nèi)存空間
server_address.sin_family=PF_INET; //IPV4協(xié)議
server_address.sin_port=htons(P_host); //端口號賦值
server_address.sin_addr.s_addr=INADDR_ANY; //本地IP地址
/*1 .創(chuàng)建套接字*/
socketfd=socket(PF_INET,SOCK_STREAM,0);
if(socketfd<0)
{
printf("服務(wù)器網(wǎng)絡(luò)套接字創(chuàng)建失敗!\n");
return -1;
}
/*2. 綁定端口,創(chuàng)建服務(wù)器*/
if(bind(socketfd,(const struct sockaddr *)&server_address,sizeof(struct sockaddr))!=0)
{
printf("服務(wù)器綁定端口失敗!\n");
return -1;
}
/*3. 設(shè)監(jiān)聽的端口數(shù)量*/
if(listen(socketfd,10)!=0)
{
printf("服務(wù)器端口監(jiān)聽失敗!\n");
return -1;
}
int i;
for(i=0;i<2;i++)
{
address_len[i]=sizeof(struct sockaddr); //計算結(jié)構(gòu)體大小 20
/*4. 等待客戶端連接*/
if((clientfd[i]=accept(socketfd,(struct sockaddr *)&client_address[i],&address_len[i]))<0)
{
printf("等待客戶端連接失敗!\n");
break;
}
//創(chuàng)建線程
if(pthread_create(&thread_id[i],NULL,fun[i],NULL)!=0)
{
printf("線程_%d_創(chuàng)建失敗!\n",i);
}
}
while(1)
{
}
//阻塞方式等待線程的結(jié)束
pthread_join(thread_id[0],NULL);
pthread_join(thread_id[1],NULL);
return 0;
}
//線程1
void *start_routine_1(void *dev)
{
while(1)
{
printf("TCP客戶端1連接!\n");
sleep(2);
}
//終止線程
pthread_exit(NULL);
}
//線程2
void *start_routine_2(void *dev)
{
while(1)
{
printf("TCP客戶端2連接!\n");
sleep(2);
}
//終止線程
pthread_exit(NULL);
}
-
Linux
+關(guān)注
關(guān)注
87文章
11351瀏覽量
210493 -
編程
+關(guān)注
關(guān)注
88文章
3639瀏覽量
94028 -
線程
+關(guān)注
關(guān)注
0文章
505瀏覽量
19762
發(fā)布評論請先 登錄
相關(guān)推薦
服務(wù)器如何處理 HTTP 請求
如何調(diào)試 HTTP 請求和響應(yīng)
socket 多線程編程實現(xiàn)方法
Python編程:處理網(wǎng)絡(luò)請求的代理技術(shù)
Linux網(wǎng)絡(luò)協(xié)議棧的實現(xiàn)
![<b class='flag-5'>Linux</b><b class='flag-5'>網(wǎng)絡(luò)</b>協(xié)議棧的實現(xiàn)](https://file1.elecfans.com/web2/M00/06/C6/wKgaombfpT-AeVQcAACjr17dpiQ190.png)
嵌入式linux開發(fā)的基本步驟有哪些?
嵌入式linux開發(fā)板芯片的工作原理
linux開發(fā)板與樹莓派的區(qū)別
linux開發(fā)板和單片機(jī)開發(fā)的區(qū)別
鴻蒙OS開發(fā)實戰(zhàn):【網(wǎng)絡(luò)管理HTTP數(shù)據(jù)請求】
![鴻蒙OS<b class='flag-5'>開發(fā)</b>實戰(zhàn):【<b class='flag-5'>網(wǎng)絡(luò)</b>管理HTTP數(shù)據(jù)<b class='flag-5'>請求</b>】](https://file1.elecfans.com/web2/M00/C5/D1/wKgZomYChGOAUaiiAADe1d8SeRY102.jpg)
鴻蒙OS開發(fā)實例:【窺探網(wǎng)絡(luò)請求】
![鴻蒙OS<b class='flag-5'>開發(fā)</b>實例:【窺探<b class='flag-5'>網(wǎng)絡(luò)</b><b class='flag-5'>請求</b>】](https://file1.elecfans.com/web2/M00/C7/36/wKgaomYGzZaAaG3mAAFjTa5gSYM677.jpg)
鴻蒙原生應(yīng)用開發(fā)-網(wǎng)絡(luò)管理HTTP數(shù)據(jù)請求
鴻蒙開發(fā)實戰(zhàn):網(wǎng)絡(luò)請求庫【axios】
![鴻蒙<b class='flag-5'>開發(fā)</b>實戰(zhàn):<b class='flag-5'>網(wǎng)絡(luò)</b><b class='flag-5'>請求</b>庫【axios】](https://file1.elecfans.com/web2/M00/C5/93/wKgZomX-4hWAGTuRAWyFifjJjx8545.jpg)
評論