套接字socket--概念和例項
阿新 • • 發佈:2018-11-11
套接字 socket
套接字概念
套接字是一種程序間通訊的方法,不同於以往介紹的的程序通訊方法的是,它並不侷限於同一臺計算機的資源,例如共享內容或者訊息佇列。
一臺機器上的程序可以使用套接字與另一臺機器上的程序通訊。因此客戶與伺服器可以分散到網路中。
同一臺機器的程序間也可以用套接字通訊。
套接字的工作過程(伺服器端)
首先,伺服器應用程式通過socket系統呼叫建立一個套接字,它是系統分配給該伺服器程序的類似檔案描述符的資源,不能與其他程序共享。
其次,伺服器程序使用bind系統呼叫個套接字命名。
接下來,伺服器程序開始等待客戶連線到這個命名套接字,呼叫listen建立一個等待佇列,以使存放來自客戶的進入連線。
最後,伺服器通過accept系統呼叫來接受客戶的連線。此時,會產生一個與原有的命名套接字不同的新套接字,它僅用於與這個特定的客戶端,而命名套接字則被保留下來繼續處理來自其他客戶的連線。
套接字的工作工程(客戶端)
呼叫socket建立一個未命名套接字,將伺服器的命名套接字作為一個地址來呼叫connect與伺服器建立連線。
一旦建立了連線,就可以像使用底層檔案描述符那樣來用套接字進行雙向的資料通訊。
套接字的屬性
套接字的特性由三個屬性決定:
域(domain):指定套接字通訊中使用的網路介質,包括地址格式。
- AF_INET,即網際網路絡,基於IP協議,並且每個對應一個埠號,套接字地址由IP地址+埠號決定
型別(type)
- 流套接字:由型別SOCK_STREAM指定,基於TCP/IP實現,提供一個有序、可靠、雙向位元組流的連線,傳送的資料不會丟失、亂序、重複。大的訊息會被分塊、傳輸、重組,很像一個檔案流。
- 資料報套接字:由SOCK_DGRAM指定,基於UDP/IP協議,不建立和維持可靠連線,開銷小,伺服器崩潰不需要客戶端重啟,因為基於資料報的伺服器不保留連線資訊
協議(protocol)
套接字舉例
客戶端程式:建立一個未命名的套接字,然後把它連線到伺服器套接字server_socket上,向伺服器寫一個字元,再讀回經伺服器處理後的一個字元。
伺服器端程式:首先建立一個伺服器套接字,繫結一個名字,然後建立一個監聽佇列,接收來自客戶程式的連線。
client1.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/un.h>
#include <unistd.h>
int main()
{
int sockfd;
int len;
struct sockaddr_un address;
int result;
char ch = 'A';
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
//根據伺服器的情況設定連續地址
address.sun_family = AF_UNIX;
strcpy(address.sun_path, "server_socket");
len = sizeof(address);
result = connect(sockfd, (struct sockaddr *)&address, len);
if (result == -1)
{
perror("oops:client1");
exit(1);
}
write(sockfd, &ch, 1);
read(sockfd, &ch, 1);
printf("char from server = %c\n", ch);
close(sockfd);
exit(0);
}
server1.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
int main()
{
int server_sockfd, client_sockfd;//定義套接字識別符號
int server_len, client_len;//地址長度
struct sockaddr_un server_address;
struct sockaddr_un client_address;
unlink("server_socket");//如果當前目錄有叫做server_socket的檔案,則刪掉
server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);//採用位元組流方式,預設協議
server_address.sun_family = AF_UNIX;
strcpy(server_address.sun_path, "server_socket");
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
listen(server_sockfd, 5);//建立長度為5的監聽佇列
while(1)//等待客戶端連線的到來
{
char ch;
printf("server waiting\n");
client_len = sizeof(client_address);//獲取客戶端的地址長度
//伺服器程序阻塞自身,知道有客戶端請求建立連線,此時生成一個新的套接字,並返回新套接子的描述符,用此新套接字與客戶進行通訊
client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);
read(client_sockfd, &ch, 1);
ch++;
write(client_sockfd, &ch, 1);
close(client_sockfd);
}
}