五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Linux socket使用-聊天系統(tǒng)

2020-07-02 00:16 作者:無情劍客Burning  | 我要投稿

聲明:謝絕一切形式的轉(zhuǎn)載

socket套接字

socket起源于Unix,而Unix/Linux基本哲學(xué)之一就是“一切皆文件”,都可以用“打開open –> 讀寫write/read –> 關(guān)閉close”模式來操作。Socket就是該模式的一個(gè)實(shí)現(xiàn), socket即是一種特殊的文件,一些socket函數(shù)就是對(duì)其進(jìn)行的操作(讀/寫IO、打開、關(guān)閉). 說白了Socket是應(yīng)用層與TCP/IP協(xié)議族通信的中間軟件抽象層,它是一組接口。在設(shè)計(jì)模式中,Socket其實(shí)就是一個(gè)門面模式,它把復(fù)雜的TCP/IP協(xié)議族隱藏在Socket接口后面,對(duì)用戶來說,一組簡(jiǎn)單的接口就是全部,讓Socket去組織數(shù)據(jù),以符合指定的協(xié)議。

TCP/IP

TCP三次握手

tcp的三次握手如下所示。

有很多面試官很特別容易問為什么兩次不行?個(gè)人感覺,兩次也不是不行。只是在有些情況下會(huì)產(chǎn)生無效的連接。 比如客戶端發(fā)起連接,由于網(wǎng)絡(luò)阻塞,服務(wù)器一直沒有收到連接請(qǐng)求,客戶端沒有收到任何回應(yīng),啟動(dòng)重傳機(jī)制,又發(fā)起了一次連接,這次很順利,然后服務(wù)端正常返回信息,第二次的連接成功了??墒?,萬萬沒想到,那個(gè)阻塞的連接經(jīng)過跋山涉水終于到了服務(wù)器端,此時(shí)服務(wù)器作何處理那? 服務(wù)器端認(rèn)為你咋又發(fā)了個(gè)請(qǐng)求呀,于是再次進(jìn)行確認(rèn),客戶端收到一條服務(wù)器端的一個(gè)確認(rèn),不予理會(huì)。可服務(wù)器卻堅(jiān)持認(rèn)為連接已經(jīng)成功,等待客戶端傳輸數(shù)據(jù),于是服務(wù)器的許多資源就浪費(fèi)了。

抓包分析

個(gè)人認(rèn)為,涉及到tcp/ip原理講解的,空講理論略顯不足,甚至有點(diǎn)"耍流氓"的感覺。"三次握手,四次揮手"這種理論書本中講述的很清楚了,下面以WireShark工具見證一下這個(gè)理論。

三次握手

通過上面可以看出三次握手的流程

  1. 客戶端向服務(wù)器端發(fā)送[SYN],seq=0

  2. 服務(wù)端向客戶端返回[SYN,ACK] Ack=1 seq=0

  3. 客戶端向服務(wù)器端返回[ACK] Ack=1

四次揮手

tcp狀態(tài)變遷圖

基本的socket函數(shù)

使用socket編程用到的函數(shù)和基本流程如下:

注意:還有兩個(gè)函數(shù)send和recieve。這兩個(gè)函數(shù)比較容易望文生義,認(rèn)為是send把數(shù)據(jù)發(fā)送出去。其實(shí)不是這樣子的,只有當(dāng)send把socket的發(fā)送緩沖區(qū)填滿的時(shí)候數(shù)據(jù)才進(jìn)行發(fā)送,通過TCP/IP協(xié)議進(jìn)行發(fā)送。進(jìn)行數(shù)據(jù)傳輸?shù)氖菂f(xié)議。

簡(jiǎn)單聊天系統(tǒng)

前面的理論知識(shí)還是很有必要了解的。之后開發(fā)程序就簡(jiǎn)單多了。先看以下效果:

服務(wù)器端代碼

  1. /*************************************************************************


  2. > File Name: ser.c


  3. > Author: 無情劍客


  4. > Mail: 2250911301@qq.com


  5. > Created Time: 2020年7月1日21時(shí)43分10秒

  6. ?************************************************************************/


  7. #include<stdio.h>


  8. #include<stdlib.h>


  9. #include<string.h>


  10. #include<sys/types.h>


  11. #include<sys/socket.h>


  12. #include<unistd.h>


  13. #include<netinet/in.h>


  14. #include<arpa/inet.h>


  15. #define PORT 6666


  16. #define BACKLOG 10


  17. #define MAXDATASIZE ?2048


  18. int main(int argc, char *argv[])


  19. {


  20. ? ?int listenfd;


  21. ? ?//創(chuàng)建一個(gè)socket描述符,此描述符僅是本主機(jī)上的一個(gè)普通文件描述符而已


  22. ? ?listenfd = socket(AF_INET, SOCK_STREAM, 0);


  23. ? ?//定義一個(gè)結(jié)構(gòu)體變量servaddr,用來記錄給定的IP和port信息,為bind函數(shù)做準(zhǔn)備


  24. ? ?struct sockaddr_in serveraddr;


  25. ? ?bzero(&serveraddr, sizeof(serveraddr));


  26. ? ?serveraddr.sin_family = AF_INET;


  27. ? ?serveraddr.sin_port = htons(PORT); //把端口轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)序,即大端模式


  28. ? ?serveraddr.sin_addr.s_addr = INADDR_ANY;


  29. ? ?//把“本地含義的描述符”綁定到一個(gè)IP和Port上,此時(shí)這個(gè)socket才具備對(duì)外連接的能力


  30. ? ?bind(listenfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));


  31. ? ?//創(chuàng)建一個(gè)監(jiān)聽隊(duì)列,用來保存用戶的請(qǐng)求連接信息(ip、port、protocol)


  32. ? ?listen(listenfd, BACKLOG);


  33. ? ?printf("======端口綁定成功,等待客戶端的連接======\n");


  34. ? ?//讓操作系統(tǒng)回填client的連接信息(ip、port、protocol)


  35. ? ?struct sockaddr_in peeraddr;


  36. ? ?socklen_t peer_len = sizeof(peeraddr);


  37. ? ?int connfd;


  38. ? ?while(1)


  39. ? ?{


  40. ? ? ? ?//accept函數(shù)從listen函數(shù)維護(hù)的監(jiān)聽隊(duì)列里取一個(gè)客戶連接請(qǐng)求處理


  41. ? ? ? ?connfd = accept(listenfd, (struct sockaddr*)&peeraddr, &peer_len);


  42. ? ? ? ?printf("\n=====================客戶端鏈接成功=====================\n");


  43. ? ? ? ?printf("IP = %s:PORT = %d\n", inet_ntoa(peeraddr.sin_addr), ? ? ? ? ntohs(peeraddr.sin_port));


  44. ? ? ? ?char buf[MAXDATASIZE];


  45. ? ? ? ?while(1)


  46. ? ? ? ?{


  47. ? ? ? ? ? ?memset(buf, '\0', MAXDATASIZE/sizeof ?(char));


  48. ? ? ? ? ? ?int recv_length = recv(connfd, buf, MAXDATASIZE/sizeof (char), 0);


  49. ? ? ? ? ? ?if(recv_length == 0)


  50. ? ? ? ? ? ?{


  51. ? ? ? ? ? ? ? ?printf("客戶端已經(jīng)關(guān)閉!\n");


  52. ? ? ? ? ? ? ? ?break;


  53. ? ? ? ? ? ?}

  54. ? ? ? ? ? ?char vul_buffer[64] ;

  55. ? ? ? ? ? ?strcpy(vul_buffer,buf);


  56. ? ? ? ? ? ?printf("客戶端說: ");


  57. ? ? ? ? ? ?fputs(vul_buffer, stdout);


  58. ? ? ? ? ? ?memset(buf, '\0', MAXDATASIZE/sizeof (char));


  59. ? ? ? ? ? ?printf("請(qǐng)輸入: ");


  60. ? ? ? ? ? ?fgets(buf, sizeof(buf), stdin);


  61. ? ? ? ? ? ?send(connfd, buf, recv_length, 0);


  62. ? ? ? ?}


  63. ? ? ? ?close(connfd);


  64. ? ? ? ?close(listenfd);


  65. ? ? ? ?return 0;


  66. ? ?}

  67. }

這里使用了strcpy這個(gè)危險(xiǎn)函數(shù),后續(xù)文章會(huì)針對(duì)這個(gè)漏洞進(jìn)行攻擊。

客戶端代碼

  1. /*************************************************************************


  2. > File Name: client.c


  3. > Author: 無情劍客


  4. > Mail: 2250911301@qq.com


  5. > Created Time: 2020年07月01日 星期三 21時(shí)44分37秒


  6. ************************************************************************/


  7. #include<stdio.h>


  8. #include<stdlib.h>


  9. #include<string.h>


  10. #include<sys/types.h>


  11. #include<sys/socket.h>


  12. #include<unistd.h>


  13. #include<netinet/in.h>


  14. #define PORT 6666


  15. #define MAXDATASIZE 2048


  16. int main(int argc, char *argv[])


  17. {


  18. ? ?if(argc != 2)


  19. ? ?{


  20. ? ? ? ?fprintf(stderr, "請(qǐng)您輸入ip地址!\n");


  21. ? ? ? ?exit(1);


  22. ? ?}


  23. ? ?int sockfd;


  24. ? ?sockfd = socket(AF_INET, SOCK_STREAM, 0);


  25. ? ?const char *server_ip = argv[1]; //從命令行獲取輸入的ip地址,此處沒有對(duì)ip地址進(jìn)行檢驗(yàn)


  26. ? ?struct sockaddr_in serveraddr;


  27. ? ?bzero(&serveraddr, sizeof(serveraddr));


  28. ? ?serveraddr.sin_family = AF_INET;


  29. ? ?serveraddr.sin_port = htons(PORT);


  30. ? ?inet_pton(AF_INET, server_ip, &serveraddr.sin_addr);


  31. ? ?connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));


  32. ? ?printf("=====================服務(wù)器鏈接成功=====================\n");


  33. ? ?char buf[MAXDATASIZE];


  34. ? ?memset(buf, 0 , ?sizeof(buf));


  35. ? ?printf("請(qǐng)輸入: ");


  36. ? ?while(fgets(buf, sizeof(buf), stdin) != NULL && (strcmp(buf, "quit")))


  37. ? ?{


  38. ? ? ? ?send(sockfd, buf, sizeof(buf), 0);


  39. ? ? ? ?memset(buf, 0, sizeof(buf));


  40. ? ? ? ?recv(sockfd, buf, sizeof(buf), 0);


  41. ? ? ? ?printf("服務(wù)器說: ");


  42. ? ? ? ?fputs(buf, stdout);


  43. ? ? ? ?memset(buf, 0, sizeof(buf));


  44. ? ? ? ?printf("請(qǐng)輸入: ");


  45. ? ?}


  46. ? ?printf("客戶端將要被關(guān)閉,下次再見\n");


  47. ? ?close(sockfd);


  48. ? ?return 0;


  49. }

使用如下命令進(jìn)行編譯

  1. gcc -o client client.c && gcc -o server ?server.c

公眾號(hào)

更多網(wǎng)絡(luò)安全,歡迎關(guān)注我的公眾號(hào):無情劍客




Linux socket使用-聊天系統(tǒng)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
江北区| 秭归县| 明光市| 乐山市| 云南省| 永昌县| 双桥区| 旬阳县| 谷城县| 正宁县| 腾冲县| 甘洛县| 太原市| 阿拉善左旗| 松潘县| 花莲县| 宝鸡市| 广宁县| 呼伦贝尔市| 海安县| 土默特右旗| 区。| 双峰县| 寿阳县| 五峰| 隆昌县| 拉萨市| 新昌县| 曲沃县| 蒙山县| 伊金霍洛旗| 庐江县| 依安县| 唐海县| 南汇区| 棋牌| 建宁县| 邯郸县| 莆田市| 盐池县| 交口县|