日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux socket通信组件,Linux下socket简单通信

發(fā)布時間:2023/12/10 linux 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux socket通信组件,Linux下socket简单通信 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

#define MAXLINE 4096

/**************程序流程*******************

1 用socket()函數(shù)創(chuàng)建一個socket

2 用bind()綁定到一個本地的地址,這樣其他的socket可以用connect()連接上去

3 用listen()指出愿意接收連接并指定進來的連接的隊列限制

4 用accept()函數(shù)來接收連接

*****************************************/

int main(int argc, char const *argv[])

{

int listenfd; //監(jiān)聽套接字描述符,管理客戶端連接到服務(wù)端的個數(shù)

int connfd; //連接套接字描述符,被send()和recv()函數(shù)所使用

struct sockaddr_in servaddr; //套接字地址結(jié)構(gòu)體

//結(jié)構(gòu)體具體定義見sockaddr_in.jpg

char buff[MAXLINE];

int n;

if((listenfd = socket(AF_INET,SOCK_STREAM,0)) == -1){

//socket函數(shù)向系統(tǒng)申請一個通信端口 原型:int socket(int domain, int type, int protocol);

//domain@ PF_INET, AF_INET: Ipv4網(wǎng)絡(luò)協(xié)議; PF_INET6, AF_INET6: Ipv6網(wǎng)絡(luò)協(xié)議

//type@ SOCK_STREAM: 提供面向連接的穩(wěn)定數(shù)據(jù)傳輸,即TCP協(xié)議。SOCK_DGRAM: 使用不連續(xù)不可靠的數(shù)據(jù)包連接。

//protocal@ 傳輸協(xié)議編號,一般設(shè)置為0就好。

printf("create socket error: %s(errno:%d)\n",strerror(errno),errno);

//errno 為全局變量,包含在中,程序出錯時自動填充。錯誤號的源代碼定義:https://www.cnblogs.com/xrcun/p/3210889.html

//strerror()函數(shù)不是線程安全的,strerror_r()是線程安全的。

return 0;

}

memset(&servaddr,0,sizeof(servaddr)); //初始化結(jié)構(gòu)體

servaddr.sin_family = AF_INET; //設(shè)置地址家族,此處為IPv4

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

//設(shè)置地址:servaddr.sin_addr.s_addr是ip地址,

//htonl()的作用:將主機的unsigned long值轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序(32位);作用相反的函數(shù)即把網(wǎng)絡(luò)字節(jié)順序轉(zhuǎn)化成主機序列為ntohl()函數(shù);htons()就是轉(zhuǎn)化為short類型的(16位兩字節(jié))

//機器上可能有多塊網(wǎng)卡,也就有多個IP地址,這時候你要選擇綁定在哪個IP上面,如果指定為INADDR_ANY,那么系統(tǒng)將綁定默認的網(wǎng)卡【即IP地址】

//servaddr.sin_addr.s_addr = inet_addr("192.168.81.130")手動設(shè)置服務(wù)器的IP地址;inet_addr()作用是將一個IP字符串轉(zhuǎn)化為一個網(wǎng)絡(luò)字節(jié)序的整數(shù)值,inet_ntoa()作用與其相反

servaddr.sin_port = htons(6666); //設(shè)置端口

if(bind(listenfd,(struct sockaddr*) &servaddr , sizeof(servaddr)) == -1){

//sockaddr的缺陷是:把目標(biāo)地址和端口信息混在一起了; sockaddr_in解決了sockaddr的缺陷,但是參數(shù)傳遞時需要類型轉(zhuǎn)換為sockaddr。

printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);

return 0;

}

if(listen(listenfd,10) == -1){

//監(jiān)聽端口后,被動套接字會等待連接,此時系統(tǒng)維護著兩個隊列,第一個隊列存放的是已建立連接的套接字(即完成三次握手后的),第二個隊列存放的是未建立連接的套接字(處在三次握手中的)。每次accept函數(shù)會將第一個隊列中的套接字返回,進行通信,以完成網(wǎng)絡(luò)傳輸。

//所以listen的第二個參數(shù)意味著這兩個隊列的總和大小

printf("listen socket error:%s(errno: %d)\n",strerror(errno),errno);

return 0;

}

printf("========== waiting for client's request =============\n");

connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);

while(1){

if( connfd == -1){

//等待客戶端連接,連接將加入到等待接受(accept())的隊列中

//第一個參數(shù)為本地(服務(wù)端監(jiān)聽描述符),第二個參數(shù)存有客戶端IP地址和端口號,第三個參數(shù)為sockaddr*指向區(qū)域的長度

//accept在有客戶端連接上來時會被阻塞

printf("accept socket error: %s(errno: %d)",strerror(errno),errno);

continue;

}

n = recv(connfd,buff,MAXLINE,0);

//buff:緩沖區(qū)名字 MAXLINE:緩沖區(qū)大小 最后一個參數(shù)(flags):

//通常flags設(shè)置為0,此時recv()函數(shù)讀取tcp 緩沖區(qū)中的數(shù)據(jù)到buf中,并從tcp 緩沖區(qū)中移除已讀取的數(shù)據(jù),

//如果把flags設(shè)置為MSG_PEEK,僅僅是把tcp 緩沖區(qū)中的數(shù)據(jù)讀取到buf中,沒有把已讀取的數(shù)據(jù)從tcp 緩沖區(qū)中移除,如果再次調(diào)用recv()函數(shù)仍然可以讀到剛才讀到的數(shù)據(jù)。

buff[n] = '\0';

//scanf之類的字符串處理函數(shù)會自動將緩沖區(qū)的最后一字節(jié)設(shè)置為 '\0',但是諸如read()等函數(shù)就不會自動設(shè)置

//TCP緩沖區(qū)大小一般分為三級,詳見 https://blog.csdn.net/nawenqiang/article/details/81503870

printf("recv msg from client: %s\n",buff);

memset(buff,0,sizeof(buff)/sizeof(char) ); //發(fā)送完一次后清空緩沖區(qū),為下一次發(fā)送做好準(zhǔn)備。

}

close(connfd);

close(listenfd);

return 0;

}

總結(jié)

以上是生活随笔為你收集整理的linux socket通信组件,Linux下socket简单通信的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。