1. 程式人生 > >本地通訊例項(AF_UNIX) socket協議通訊

本地通訊例項(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