本地通訊例項(AF_UNIX) socket協議通訊
程式說明:
程式裡包含服務端和客戶端兩個程式,它們之間使用 AF_UNIX 實現本機資料流通訊。使用 AF_UNIX 域實際上是使用本地 socket 檔案來通訊。
伺服器端程式碼:
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <sys/un.h> #include <unistd.h> #include <stdlib.h> int main (int argc, char *argv[]) { int server_sockfd, client_sockfd; int server_len, client_len; struct sockaddr_un server_address; /*宣告一個UNIX域套接字結構*/ struct sockaddr_un client_address; int i, bytes; char ch_send, ch_recv; unlink ("server_socket"); /*刪除原有server_socket物件*/ /*建立 socket, 通訊協議為AF_UNIX, SCK_STREAM 資料方式*/ server_sockfd = socket (AF_UNIX, SOCK_STREAM, 0); /*配置伺服器資訊(通訊協議)*/ server_address.sun_family = AF_UNIX; /*配置伺服器資訊(socket 物件)*/ strcpy (server_address.sun_path, "server_socket"); /*配置伺服器資訊(伺服器地址長度)*/ server_len = sizeof (server_address); /*繫結 socket 物件*/ bind (server_sockfd, (struct sockaddr *)&server_address, server_len); /*監聽網路,佇列數為5*/ listen (server_sockfd, 5); printf ("Server is waiting for client connect...\n"); client_len = sizeof (client_address); /*接受客戶端請求; 第2個引數用來儲存客戶端地址; 第3個引數用來儲存客戶端地址的大小*/ /*建立(返回)一個到客戶端的檔案描述符,用以對客戶端的讀寫操作*/ client_sockfd = accept (server_sockfd, (struct sockaddr *)&server_address, (socklen_t *)&client_len); if (client_sockfd == -1) { perror ("accept"); exit (EXIT_FAILURE); } printf ("The server is waiting for client data...\n"); for (i = 0, ch_send = '1'; i < 5; i++, ch_send++) { if ((bytes = read (client_sockfd, &ch_recv, 1)) == -1) { perror ("read"); exit (EXIT_FAILURE); } printf ("The character receiver from client is %c\n", ch_recv); sleep (1); if ((bytes = write (client_sockfd, &ch_send, 1)) == -1) { perror ("read"); exit (EXIT_FAILURE); } } close (client_sockfd); unlink ("server socket"); }
客戶端程式碼:
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <sys/un.h> #include <unistd.h> #include <stdlib.h> int main (int argc, char *argv[]) { struct sockaddr_un address; int sockfd; int len; int i, bytes; int result; char ch_recv, ch_send; /*建立socket,AF_UNIX通訊協議,SOCK_STREAM資料方式*/ if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { perror ("socket"); exit (EXIT_FAILURE); } address.sun_family = AF_UNIX; strcpy (address.sun_path, "server_socket"); len = sizeof (address); /*向伺服器傳送連線請求*/ result = connect (sockfd, (struct sockaddr *)&address, len); if (result == -1) { printf ("ensure the server is up\n"); perror ("connect"); exit (EXIT_FAILURE); } for (i = 0, ch_send = 'A'; i < 5; i++, ch_send++) { if ((bytes = write(sockfd, &ch_send, 1)) == -1) { /*發訊息給伺服器*/ perror ("write"); exit (EXIT_FAILURE); } sleep (2); /*休息二秒鐘再發一次*/ if ((bytes = read (sockfd, &ch_recv, 1)) == -1) { /*接收訊息*/ perror ("read"); exit (EXIT_FAILURE); } printf ("receive from server data is %c\n", ch_recv); } close (sockfd); return (0); }
程式說明:
先執行伺服器端,然後再執行客戶端可以在兩邊同時看到輸出。伺服器端先執行後會出現如下提示:
引用
./sock_local_server
Server is waiting for client connect...
這表示,伺服器端已經被阻塞到到 accept() 這裡,伺服器就在此等候客戶端的連線。
如果不是先執行伺服器端,而直接執行客戶端,那麼客戶端會提示:
引用
./sock_local_client
ensure the server is up
connect: Connection refused
提示伺服器沒有準備好,連線被拒絕,從而直接退出程式。
如果伺服器和客戶端依次執行,可以在兩邊看到輸出:
伺服器端:
引用
./sock_local_server
Server is waiting for client connect...
The server is waiting for client data...
The character receiver from client is A
The character receiver from client is B
The character receiver from client is C
The character receiver from client is D
The character receiver from client is E
客戶端:
引用
./sock_local_client
receive from server data is 1
receive from server data is 2
receive from server data is 3
receive from server data is 4
receive from server data is 5