套接字是一種程序間的通訊的方法,不同於以往介紹的程序間通訊方法的是,它並不侷限於同一臺計算機的資源,例如檔案系統空間,共享記憶體或者訊息佇列。套接字可以認為是對管道概念的擴充套件——一台機器上的程序可以使用套接字與另一台機器上的程序通訊。因此客戶與伺服器可以分散在網路中。同一臺機器上的程序間也可以用套接字通訊。套接字是一種通訊機制,客戶/伺服器系統既可以在本地單機上執行,也可以在網路中執行。套接字與管道的區別:它明確區分客戶與伺服器,可以實現將多個客戶連線到乙個伺服器。
套接字的工作過程(伺服器端):首先,伺服器應用程式通過socket系統呼叫建立乙個套接字,它是系統分配給該伺服器程序的類似檔案描述符的資源,不能與其他程序共享。其次,伺服器程序使用bind系統呼叫給套接字命名。本地套接字的名字是linux檔案系統的檔名,一般放在/tmp或者/usr/tmp 目錄下。網路套接字的名字是與客戶相連線的特定網路有關的服務識別符號。此識別符號允許linux將進入的針對特定埠號的連線轉到正確的伺服器程序。接下來,伺服器程序開始等待客戶連線到這個命名套接字,呼叫listen建立乙個等待佇列以便存放來自客戶的進入連線。最後,伺服器通過accept系統呼叫來接受客戶的連線。此時,會產生乙個與原有的命名套接字不同的新套接字,它僅用於與這個特定的客戶通訊,而命名套接字則被保留下來繼續處理來自其他客戶的連線。
套接字的工作過程(客戶端):呼叫socket建立乙個未命名套接字,將伺服器的命名套接字作為乙個位址來呼叫connect與伺服器建立連線。一旦建立了連線,就可以像使用底層檔案描述符那樣來用套接字進行雙向的資料通訊。
tcp協議
服務端tcp_server.c
#include #include #include #include #include int main(int argc, char *ar**)
/*將套接字繫結到伺服器的網路位址上*/
if (bind(server_sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))<0)
/*監聽連線請求--監聽佇列長度為5*/
listen(server_sockfd,5);
sin_size=sizeof(struct sockaddr_in);
/*等待客戶端連線請求到達*/
if((client_sockfd=accept(server_sockfd,(struct sockaddr *)&remote_addr,&sin_size))<0)
printf("accept client %s/n",inet_ntoa(remote_addr.sin_addr));
len=send(client_sockfd,"welcome to my server/n",21,0);//傳送歡迎資訊
/*接收客戶端的資料並將其傳送給客戶端--recv返回接收到的位元組數,send返回傳送的位元組數*/
while((len=recv(client_sockfd,buf,bufsiz,0))>0)) }
close(client_sockfd);
close(server_sockfd);
return 0;
}
tcp協議
客戶端 tcp_client.c
#include #include #include #include #include int main(int argc, char *ar**)
/*將套接字繫結到伺服器的網路位址上*/
if(connect(client_sockfd,(struct sockaddr *)&remote_addr,sizeof(struct sockaddr))<0)
printf("connected to server/n");
len=recv(client_sockfd,buf,bufsiz,0);//接收伺服器端資訊
buf[len]='/0';
printf("%s",buf); //列印伺服器端資訊
/*迴圈的傳送接收資訊並列印接收資訊--recv返回接收到的位元組數,send返回傳送的位元組數*/
while(1)
close(client_sockfd);//關閉套接字
return 0;
}
udp協議:
伺服器端:udp_server.c
#include #include #include #include #include int main(int argc, char *ar**)
/*將套接字繫結到伺服器的網路位址上*/
if (bind(server_sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))<0)
sin_size=sizeof(struct sockaddr_in);
printf("waiting for a packet.../n");
/*接收客戶端的資料並將其傳送給客戶端--recvfrom是無連線的*/
if((len=recvfrom(server_sockfd,buf,bufsiz,0,(struct sockaddr *)&remote_addr,&sin_size))<0)
printf("received packet from %s:/n",inet_ntoa(remote_addr.sin_addr));
buf[len]='/0';
printf("contents: %s/n",buf);
close(server_sockfd);
return 0;
}
客戶端:udp_client.c
#include #include #include #include #include int main(int argc, char *ar**)
strcpy(buf,"this is a test message");
printf("sending: '%s'/n",buf);
sin_size=sizeof(struct sockaddr_in);
/*向伺服器傳送資料報*/
if((len=sendto(client_sockfd,buf,strlen(buf),0,(struct sockaddr *)&remote_addr,sizeof(struct sockaddr)))<0)
close(client_sockfd);
return 0;
}
socket程式設計之TCP單程序的伺服器
今天介紹的是基於ipv4的socket網路程式設計,我們知道socket api是一層的抽象的網路程式設計介面,但各網路協議的位址卻是各不相同的。下圖是sockaddr資料結構圖 ipv4和ipv6的位址格式定義在netinet in.h中,ipv4位址用sockaddr in結構體表示,包括16位...
PHP多程序協作程式設計之 socket
基本思路 通過socket請求其他php腳步,實現php的多程序的非同步執行。廢話就不多說了,請看下面的腳步並執行之。a.php function runthread function a function b if isset get act get act a if get act a else...
PHP多程序協作程式設計之 socket
基本思路 通過socket請求其他php腳步,實現php的多程序的非同步執行。廢話就不多說了,請看下面的腳步並執行之。function runthread function a function b if isset get act get act a if get act a else if ge...