新聞中心
隨著計算機技術(shù)的不斷發(fā)展,Linux作為一個開源的操作系統(tǒng),在實現(xiàn)高效通信方面顯得尤為出色。其中,套接字通信技術(shù)是一種非常重要的通信方式。本文將從概念、分類、實現(xiàn)等多個方面。

一、概念
套接字通信技術(shù)(Socket Programming)是一種應(yīng)用程序編寫網(wǎng)絡(luò)通信的方法,通常也稱為網(wǎng)絡(luò)套接字或網(wǎng)絡(luò)編程。套接字是指應(yīng)用程序中進行網(wǎng)絡(luò)通信時所使用的接口,是通信的一種方式。
Linux的套接字是基于文件的輸入/輸出方法,也就是說,套接字也是一種文件描述符。Linux中所有的輸入/輸出都是通過文件描述符進行的,所以套接字本質(zhì)上也是一種文件描述符。
二、分類
linux套接字通信技術(shù)分為兩類:流套接字(SOCK_STREAM)和數(shù)據(jù)報套接字(SOCK_DGRAM)。
流套接字提供了一種面向連接的通信方式,數(shù)據(jù)在傳輸時保證了數(shù)據(jù)的可靠性,但是也存在一些缺點,比如發(fā)送數(shù)據(jù)的順序可能與接收數(shù)據(jù)的順序不一致。流套接字通常使用TCP協(xié)議進行通信。
數(shù)據(jù)報套接字則提供了一種面向消息的通信方式,數(shù)據(jù)在傳輸時保證了數(shù)據(jù)的順序,但是不保證數(shù)據(jù)的可靠性。數(shù)據(jù)報套接字通常使用UDP協(xié)議進行通信。
三、實現(xiàn)
Linux的套接字通信技術(shù)的實現(xiàn)基于兩個系統(tǒng)調(diào)用:socket()和bind()。socket()系統(tǒng)調(diào)用用于創(chuàng)建一個新的套接字,包含了套接字類型、協(xié)議類型和協(xié)議族等信息。bind()用于將一個特定的地址和套接字進行綁定。
接著,可以使用listen()進行監(jiān)聽,accept()進行連接,發(fā)送數(shù)據(jù)使用send(),接收數(shù)據(jù)使用recv()。
當(dāng)使用TCP協(xié)議進行通信時,通常需要進行三次握手來建立連接。具體過程如下:
之一次握手:客戶端向服務(wù)器發(fā)送一個SYN報文,并標(biāo)志位SYN=1,同時選擇一個初始的序列號seq=x。
第二次握手:服務(wù)器收到SYN報文,必須確認客戶端的SYN,同時自己也要發(fā)送一個SYN報文,標(biāo)志位SYN=1,同時選擇一個初始的序列號seq=y。
第三次握手:客戶端收到服務(wù)器的SYN報文,必須確認服務(wù)器的SYN。
當(dāng)連接建立好之后,可以通過send()和recv()進行數(shù)據(jù)的傳輸。
四、
Linux套接字通信技術(shù)是Linux系統(tǒng)中一種非常重要的通信方式,其實現(xiàn)基于socket()和bind()等系統(tǒng)調(diào)用。在使用流套接字時,通信采用TCP協(xié)議,需要進行三次握手來建立連接;在使用數(shù)據(jù)報套接字時,通信采用UDP協(xié)議,不存在三次握手過程。
由于其通信方式的高效性和可靠性,Linux套接字通信技術(shù)在很多領(lǐng)域得到了廣泛應(yīng)用,比如網(wǎng)絡(luò)及服務(wù)器通信、網(wǎng)絡(luò)游戲等領(lǐng)域。
成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián),建站經(jīng)驗豐富以策略為先導(dǎo)10多年以來專注數(shù)字化網(wǎng)站建設(shè),提供企業(yè)網(wǎng)站建設(shè),高端網(wǎng)站設(shè)計,響應(yīng)式網(wǎng)站制作,設(shè)計師量身打造品牌風(fēng)格,熱線:028-86922220linux系統(tǒng)的進程間通信有哪幾種方式
數(shù)據(jù)傳輸
一個進程需要將它的數(shù)據(jù)發(fā)送給另一個進程,發(fā)送的數(shù)據(jù)量在一個字節(jié)到幾M字節(jié)之間
共享數(shù)據(jù)
多個進程想要操作共享數(shù)據(jù),一個進程對共享數(shù)據(jù)
通知事
一個進程需要向另一個或一組進程發(fā)送消息,通知它(它們)發(fā)生了某種事件(如進程終止時要通知父進程)。
資源共享
多個進程之間共享同樣的資源。為了作到這一點廳拍,需要內(nèi)核提供鎖和同步機制。
進程控制
有些進程希望完全控制另一個進程的執(zhí)行(如Debug進程),此時控制進程希望能夠攔截另一個進程的所有陷入和異常,并能夠及時知道它的狀態(tài)改變。
Linux 進程間通信(IPC)的發(fā)展
linux下的進程通信手段基本上是從Unix平臺上的進程通信手段繼承而來的。而對Unix發(fā)展做出重大貢獻的兩大主力AT&T的貝爾實驗室及BSD(加州大學(xué)伯克利分校的伯克利軟件發(fā)布中心)在進程間通信方面的側(cè)重點有所不同。
前者對Unix早期的進程間通信手段進行了系統(tǒng)的改進和擴充,形成了“system V IPC”,通信進程局限在單個計算機內(nèi);
后者則跳過了該限制,形成了基于套接口(socket)的進程間通信機制。
Linux則把兩者繼承了下來
早期UNIX進程間通信
基于System V進程間通信
基于Socket進程間通信
POSIX進程間通信。
UNIX進程間通信方式包括:管道、FIFO、信號。
System V進程間通信方式包括:System V消息隊列、System V信號燈、System V共享內(nèi)存
POSIX進程間通信包括:posix消息隊列、posix信號燈、posix共享內(nèi)存。
由于Unix版本的多樣性,電子電氣工程協(xié)會(IEEE)開發(fā)了一個獨立的Unix標(biāo)準(zhǔn),這個新的ANSI Unix標(biāo)準(zhǔn)被稱為計算機環(huán)境的可移植性操作系統(tǒng)界面(PSOIX)?,F(xiàn)有大部分Unix和流行版本都是遵循POSIX標(biāo)準(zhǔn)的,而Linux從一開始就遵循POSIX標(biāo)準(zhǔn);
BSD并不是沒有涉足單機內(nèi)的進程間通信(socket本身就可以用于單機內(nèi)的進程間通信)。事實上,很多Unix版本的單機IPC留有BSD的痕跡,如4.4BSD支持的匿名內(nèi)存映射、4.3+BSD對可靠信號語義的實現(xiàn)等等。
linux使用的進程間通信方式
管道(pipe),流管道(s_pipe)和有名管道(FIFO)
信號(signal)
消息隊列
共享內(nèi)存
信號轎清量
套接字(socket)
管道( pipe )
管道這種通訊方式有兩種限制,一是半雙工的通信,數(shù)據(jù)只能單向流動,二是只能在具有親緣關(guān)系的進程間使用。進程的親緣關(guān)系通常是指父子進程關(guān)系。
流管道s_pipe: 去除了之一種限制,可以雙向傳輸.
管道可用于具有親緣關(guān)系進程間的通信,命名管道:name_pipe克服了管道沒有名字的限制,因此,除具有管道所具有的功能外,它還允許無親緣關(guān)系進程間的通信;
信號量( semophore )
信號量是一個計數(shù)器,可以用來控制多個進程對共享資源的訪問。它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內(nèi)不同線程之間的同步手段。
信號是比較復(fù)雜的通信方式,用于通知接受進程有某種事件發(fā)生,除了用于進程間通信外,進程還可以發(fā)送信號給進程本身;linux除了支持Unix早期信號語義函數(shù)sigal外,還支持語義符合Posix.1標(biāo)準(zhǔn)的信號函數(shù)sigaction(實際上,該扮帆羨函數(shù)是基于BSD的,BSD為了實現(xiàn)可靠信號機制,又能夠統(tǒng)一對外接口,用sigaction函數(shù)重新實現(xiàn)了signal函數(shù));
消息隊列( message queue )
消息隊列是由消息的鏈表,存放在內(nèi)核中并由消息隊列標(biāo)識符標(biāo)識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點。
消息隊列是消息的鏈接表,包括Posix消息隊列system V消息隊列。有足夠權(quán)限的進程可以向隊列中添加消息,被賦予讀權(quán)限的進程則可以讀走隊列中的消息。消息隊列克服了信號承載信息量少,管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點。
信號 ( singal )
信號是一種比較復(fù)雜的通信方式,用于通知接收進程某個事件已經(jīng)發(fā)生。
主要作為進程間以及同一進程不同線程之間的同步手段。
共享內(nèi)存( shared memory )
共享內(nèi)存就是映射一段能被其他進程所訪問的內(nèi)存,這段共享內(nèi)存由一個進程創(chuàng)建,但多個進程都可以訪問。共享內(nèi)存是最快的 IPC 方式,它是針對其他進程間通信方式運行效率低而專門設(shè)計的。它往往與其他通信機制,如信號量,配合使用,來實現(xiàn)進程間的同步和通信。
使得多個進程可以訪問同一塊內(nèi)存空間,是最快的可用IPC形式。是針對其他通信機制運行效率較低而設(shè)計的。往往與其它通信機制,如信號量結(jié)合使用,來達到進程間的同步及互斥。
套接字( socket )
套解口也是一種進程間通信機制,與其他通信機制不同的是,它可用于不同機器間的進程通信
更為一般的進程間通信機制,可用于不同機器之間的進程間通信。起初是由Unix系統(tǒng)的BSD分支開發(fā)出來的,但現(xiàn)在一般可以移植到其它類Unix系統(tǒng)上:Linux和System V的變種都支持套接字。
進程間通信各種方式效率比較
類型
無連接
可靠
流控制
記錄消息類型
優(yōu)先級
普通PIPE N Y YN
流PIPE N Y YN
命名PIPE(FIFO) N Y YN
消息隊列 N Y YY
信號量 N Y YY
共享存儲 N Y YY
UNIX流SOCKET N Y YN
UNIX數(shù)據(jù)包SOCKET Y Y NN
注:無連接: 指無需調(diào)用某種形式的OPEN,就有發(fā)送消息的能力流控制:
如果系統(tǒng)資源短缺或者不能接收更多消息,則發(fā)送進程能進行流量控制
各種通信方式的比較和優(yōu)缺點
管道:速度慢,容量有限,只有父子進程能通訊
FIFO:任何進程間都能通訊,但速度慢
消息隊列:容量受到系統(tǒng)限制,且要注意之一次讀的時候,要考慮上一次沒有讀完數(shù)據(jù)的問題
信號量:不能傳遞復(fù)雜消息,只能用來同步
共享內(nèi)存區(qū):能夠很容易控制容量,速度快,但要保持同步,比如一個進程在寫的時候,另一個進程要注意讀寫的問題,相當(dāng)于線程中的線程安全,當(dāng)然,共享內(nèi)存區(qū)同樣可以用作線程間通訊,不過沒這個必要,線程間本來就已經(jīng)共享了同一進程內(nèi)的一塊內(nèi)存
如果用戶傳遞的信息較少或是需要通過信號來觸發(fā)某些行為.前文提到的軟中斷信號機制不失為一種簡捷有效的進程間通信方式.
但若是進程間要求傳遞的信息量比較大或者進程間存在交換數(shù)據(jù)的要求,那就需要考慮別的通信方式了。
無名管道簡單方便.但局限于單向通信的工作方式.并且只能在創(chuàng)建它的進程及其子孫進程之間實現(xiàn)管道的共享:
有名管道雖然可以提供給任意關(guān)系的進程使用.但是由于其長期存在于系統(tǒng)之中,使用不當(dāng)容易出錯.所以普通用戶一般不建議使用。
消息緩沖可以不再局限于父子進程,而允許任意進程通過共享消息隊列來實現(xiàn)進程間通信,并由系統(tǒng)調(diào)用函數(shù)來實現(xiàn)消息發(fā)送和接收之間的同步,從而使得用戶在使用消息緩沖進行通信時不再需要考慮同步問題,使用方便,但是信息的復(fù)制需要額外消耗CPU的時間,不適宜于信息量大或操作頻繁的場合。
共享內(nèi)存針對消息緩沖的缺點改而利用內(nèi)存緩沖區(qū)直接交換信息,無須復(fù)制,快捷、信息量大是其優(yōu)點。
但是共享內(nèi)存的通信方式是通過將共享的內(nèi)存緩沖區(qū)直接附加到進程的虛擬地址空間中來實現(xiàn)的,因此,這些進程之間的讀寫操作的同步問題操作系統(tǒng)無法實現(xiàn)。必須由各進程利用其他同步工具解決。另外,由于內(nèi)存實體存在于計算機系統(tǒng)中,所以只能由處于同一個計算機系統(tǒng)中的諸進程共享。不方便網(wǎng)絡(luò)通信。
共享內(nèi)存塊提供了在任意數(shù)量的進程之間進行高效雙向通信的機制。每個使用者都可以讀取寫入數(shù)據(jù),但是所有程序之間必須達成并遵守一定的協(xié)議,以防止諸如在讀取信息之前覆寫內(nèi)存空間等競爭狀態(tài)的出現(xiàn)。
不幸的是,Linux無法嚴(yán)格保證提供對共享內(nèi)存塊的獨占訪問,甚至是在您通過使用IPC_PRIVATE創(chuàng)建新的共享內(nèi)存塊的時候也不能保證訪問的獨占性。 同時,多個使用共享內(nèi)存塊的進程之間必須協(xié)調(diào)使用同一個鍵值。
linux中關(guān)于流式套接字編程代碼的解釋,求大神把每行代碼加上注釋,具體一點
樓上寫的真不少,30-分值的送他,辛苦了。
服務(wù)器端
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char* argv)
{
int server_sockfd,client_sockfd;
int server_len,client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
//獲得一個socket文件描述符,使用tcp ip 協(xié)議
server_sockfd=socket(AF_INET,SOCK_STREAM,0);
server_address.sin_family=AF_INET;
//設(shè)置服務(wù)器端接巖困受任何主機的請求
server_address.sin_addr.s_addr=htonl(INADDR_ANY);
//使用端口9734 來接受請求
server_address.sin_port=htons(9734);
server_len=sizeof(server_address);
//綁定socket
bind(server_sockfd,(struct sockaddr *)&server_address,server_len);
//監(jiān)聽連接請求,連接請求隊列 大小為 5
listen(server_sockfd,5);
while(1)
{
char ch;
printf(“server waiting\n”);
client_len=sizeof(client_address);
//接受client 端的連接請求,如果沒有連接請求,該進程將阻塞
client_sockfd=accept(server_sockfd,(struct sockaddr *)&client_address,&client_len);
//讀數(shù)據(jù)
read(client_sockfd,&ch,1);
ch++;
//寫數(shù)據(jù)
write(client_sockfd,&ch,1);
//關(guān)閉與client端的連接
close(client_sockfd);
}
}
客戶端
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char* argv)
{
int sockfd;
int len;
struct 哪蠢sockaddr_in address;
int result;
char ch=’A’;
//設(shè)置需要連接服務(wù)器的 ip port
sockfd=socket(AF_INET,SOCK_STREAM,0);
address.sin_family=AF_INET;
address.sin_addr.s_addr=inet_addr(“127.0.0.1”);
address.sin_port=htons(9734);
len=sizeof(address);
//連接服務(wù)器
result=connect(sockfd,(struct sockaddr *)&address,len);
if(result==-1)
{
perror(“oops:client3”);
exit(1);
}
//寫數(shù)據(jù)
write(sockfd,&ch,1);
//讀數(shù)據(jù)
read(sockfd,&ch,1);
printf(“char from server=%c\n”,ch);
//關(guān)李棗陪閉與服務(wù)器的連接
close(sockfd);
exit(0);
}
關(guān)于你的問題:
1.簡單的方法,設(shè)置socket套接字為非阻塞模式,然后輪詢,并查看是否超時。
或者是使用select poll 等方法 ,設(shè)置超時時間。
或者 使用 alarm 信號,都可以。
2..每當(dāng)接收到一個client 端的連接請求,就開辟一個線程為之服務(wù)。
或者使用select poll epoll等方法,推薦這個。
3.你是指的是處理信號嗎?這個有專門的函數(shù) signal 可以處理。
Linux下Socket編程 怎樣實現(xiàn)客戶端之間互相通信
網(wǎng)絡(luò)的Socket數(shù)據(jù)傳輸是一種特殊的I/O,Socket也是一種文件描述符。Socket也具有一個類似于打開文件的函數(shù)調(diào)用Socket(),該函數(shù)返回一個整型的Socket描述符,隨后的連接建立、數(shù)據(jù)傳輸?shù)炔僮鞫际峭ㄟ^該Socket實現(xiàn)的。
下面用Socket實現(xiàn)一個windows下的c語言socket通信例子,這里我們客戶端傳遞一個字符串,服務(wù)器端進行接收。
【服務(wù)器端】
#include “stdafx.h”
#include
#include
#include
#define SERVER_PORT 5208 //偵聽端口
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int ret, nLeft, length;
SOCKET sListen, sServer; //偵聽套接字,連接套接字
struct sockaddr_in saServer, saClient; //地址信息
char *ptr;//用于遍歷信息的指針
//WinSock初始化
wVersionRequested=MAKEWORD(2, 2); //希望使用的WinSock DLL 的版本
ret=WSAStartup(wVersionRequested, &wsaData);
if(ret!=0)
{
printf(“WSAStartup() failed!\n”);
return;
}
//創(chuàng)建Socket,使用TCP協(xié)議
sListen=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sListen == INVALID_SOCKET)
{
WSACleanup();
printf(“socket() faild!\n”);
return;
}
//構(gòu)建本地地址信息
saServer.sin_family = AF_INET; //地址家族
saServer.sin_port = htons(SERVER_PORT); //注意轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)序
saServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //使用INADDR_ANY 指示任意地址
//綁定
ret = bind(sListen, (struct sockaddr *)&saServer, sizeof(saServer));
if (ret == SOCKET_ERROR)
{
模核printf(“bind() faild! code:%d\n”, WSAGetLastError());
closesocket(sListen); //關(guān)閉套接字
WSACleanup();
return;
}
//偵聽連接請求
ret = listen(sListen, 5);
if (ret == SOCKET_ERROR)
{
printf(“l(fā)isten() faild! code:%d\n”, WSAGetLastError());
closesocket(sListen); //關(guān)閉套接字
return;
}
printf(“Waiting for client connecting!\n”);
printf(“Tips: Ctrl+c to quit!\n”);
//阻塞等待接受客戶端連接
while(1)//循環(huán)監(jiān)聽客戶端,永遠不停止,所以,在本項目中,我們沒有心跳包。
{
length = sizeof(saClient);
散碼喚 sServer = accept(sListen, (struct sockaddr *)&saClient, &length);
if (sServer == INVALID_SOCKET)
{
printf(“accept() faild! code:%d\n”, WSAGetLastError());
closesocket(sListen); //關(guān)閉套接字
WSACleanup();
return;
}
char receiveMessage;
nLeft = sizeof(receiveMessage);
ptr = (char *)&receiveMessage;
while(nLeft>0)
{
//接收數(shù)據(jù)
ret = recv(sServer, ptr, 5000, 0);
if (ret == SOCKET_ERROR)
{
printf(“recv() failed!\n”);
return;
}
if (ret == 0) //客戶端已經(jīng)關(guān)沖凱閉連接
{
printf(“Client has closed the connection\n”);
break;
}
nLeft -= ret;
ptr += ret;
}
printf(“receive message:%s\n”, receiveMessage);//打印我們接收到的消息。
}
// closesocket(sListen);
// closesocket(sServer);
// WSACleanup();
}
【客戶端】
#include “stdafx.h”
#include
#include
#include
#define SERVER_PORT 5208 //偵聽端口
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int ret;
SOCKET sClient; //連接套接字
struct sockaddr_in saServer; //地址信息
char *ptr;
BOOL fSuccess = TRUE;
//WinSock初始化
wVersionRequested = MAKEWORD(2, 2); //希望使用的WinSock DLL的版本
ret = WSAStartup(wVersionRequested, &wsaData);
if(ret!=0)
{
printf(“WSAStartup() failed!\n”);
return;
}
//確認WinSock DLL支持版本2.2
if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2)
{
WSACleanup();
printf(“Invalid WinSock version!\n”);
return;
}
//創(chuàng)建Socket,使用TCP協(xié)議
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sClient == INVALID_SOCKET)
{
WSACleanup();
printf(“socket() failed!\n”);
return;
}
//構(gòu)建服務(wù)器地址信息
saServer.sin_family = AF_INET; //地址家族
saServer.sin_port = htons(SERVER_PORT); //注意轉(zhuǎn)化為網(wǎng)絡(luò)節(jié)序
saServer.sin_addr.S_un.S_addr = inet_addr(“192.168.1.127”);
//連接服務(wù)器
ret = connect(sClient, (struct sockaddr *)&saServer, sizeof(saServer));
if (ret == SOCKET_ERROR)
{
printf(“connect() failed!\n”);
closesocket(sClient); //關(guān)閉套接字
WSACleanup();
return;
}
char sendMessage=”hello this is client message!”;
ret = send (sClient, (char *)&sendMessage, sizeof(sendMessage), 0);
if (ret == SOCKET_ERROR)
{
printf(“send() failed!\n”);
}
else
printf(“client info has been sent!”);
closesocket(sClient); //關(guān)閉套接字
WSACleanup();
}
網(wǎng)絡(luò)的Socket數(shù)據(jù)傳輸是一種特殊的I/O,Socket也是一種文件描述符。Socket也具有一個類似于打開文件的函數(shù)調(diào)用Socket(),該函數(shù)返回一個整型的Socket描述符,隨后的連接建立、數(shù)據(jù)傳輸?shù)炔僮鞫际峭ㄟ^該銀鉛搜Socket實現(xiàn)的。下面用Socket實現(xiàn)一個windows下的c語言socket通信例子,這里我們客戶端傳遞一個字符串,服務(wù)器端進行接收。
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
【服務(wù)鋒歷激嘩器端】
#include “stdafx.h”
#include
#include
#include
#define SERVER_PORT 5208 //偵聽端口
void main()
關(guān)于linux套接字通信的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
成都網(wǎng)站建設(shè)選創(chuàng)新互聯(lián)(?:028-86922220),專業(yè)從事成都網(wǎng)站制作設(shè)計,高端小程序APP定制開發(fā),成都網(wǎng)絡(luò)營銷推廣等一站式服務(wù)。
網(wǎng)站題目:深入剖析Linux套接字通信技術(shù)(linux套接字通信)
文章網(wǎng)址:http://m.fisionsoft.com.cn/article/cdsjedd.html


咨詢
建站咨詢
