一起talk C栗子吧(第一百五十六回:C语言实例--基于AF_UNIX域的流套接字通信)

时间:2022-09-11 22:29:39

各位看官们,大家好,上一回中咱们说的获取socket通信地址的例子,这一回咱们说的例子是:基于AF_UNIX域的流套接字通信 。闲话休提,言归正转。让我们一起talk C栗子吧!

看官们,我们在前面章回中介绍了套接字的通信过程以及套接字的的细节,总感觉还缺少些什么,一时还真是想不起来。这好比我们有了食谱也有了食材,那么我们就可以做一道美味的佳肴了。啊!有了。一提到美味的佳肴,灵感就来了。我们缺少的是对套接字的综合演练,也就是把前面章回中知识串在一起,然后举一个综合使用套接字知识进行套接字通信的例子。这样的例子,就是一道美味佳肴呀,接下来让我们一起制作这美味佳肴吧。我们的第一道佳肴是:基于AF_UNIX域的流套接字通信。

  • 制作第一道佳肴的菜谱:流套接字过程。
  • 制作第一道佳肴的食材:流套接字的接口,套接字属性,套接字地址信息。

看官们,以上的内容,我们在前面章回中都详细介绍过,如果大家忘记的话,可以参考前面的内容,重点是第一百四十七回的内容,因为这是我们的菜谱。多说无益,我们通过具体的代码来演示:

服务器端的通信过程及其代码

//1. 创建服务器端套接字
    server_fd = socket(AF_UNIX,SOCK_STREAM,0);
//2.设置服务器端套接字的属性:域,类型和协议;
    memset(&address,0,sizeof(struct sockaddr_un) );
    address.sun_family = AF_UNIX;
    strncpy(address.sun_path,SOCKET_PATH,sizeof(address.sun_path)-1 );
//3.把服务器端的套接字和服务器的地址绑定在一起
    addr_len = sizeof(struct sockaddr_un);
    res = bind(server_fd,(struct sockaddr *)&address,addr_len);
//4.创建套接字队列,为通信做好准备,开始监听客户端发来的通信连接请求
    res = listen(server_fd,2);
//5.接受客户端发来的连接请求,并且获得与客户端匹配的socket
    client_fd = accept(server_fd,NULL,NULL);
//6.通过套接字读取数据
    res = read(client_fd,buf,BUF_SIZE);
    printf("[server] receiving data (%s) from client by socket\n",buf);
//7.释放套接字,关闭通信
    res = close(client_fd);
    res = close(server_fd);

客户端的通信过程及其代码

//1.创建客户端套接字;
    client_fd = socket(AF_UNIX,SOCK_STREAM,0);
//2.设置客户端套接字的属性:域,类型和协议;
    memset(&address,0,sizeof(struct sockaddr_un) );
    address.sun_family = AF_UNIX;
    strncpy(address.sun_path,SOCKET_PATH,sizeof(address.sun_path)-1 );
    addr_len = sizeof(struct sockaddr_un);
//3.使用客户端套接字和服务器进行连接;
    res = connect(client_fd,(struct sockaddr *)&address,addr_len);
//4.通过套接字发送数据;
    printf("[client] sending data (%s )to server by socket \n",buf);
    res = write(client_fd,buf,sizeof(buf) );
//5.释放套接字,断开客户端与服务器端的通信;
    res = close(client_fd);

看官们,以上是核心代码,完整的代码放到了我的资源中,大家可以点击这里下载使用。

我们需要把服务器端的代码和客户端的代码分别进行编译,并且编译成不同的可以执行文件:

$ gcc Ex090_UnixStreamSocketClient.c  -o client  //编译客户端
$ gcc Ex090_UnixStreamSocketServer.c  -o server  //编译服务器端

看官们,美味佳肴做好了,我们一起来品尝下,怎么品尝?当然是运行程序了呀,难道你要把代码吃下去吗?下面是程序的运行结果,请大家参考:

$ ./server  &          //在后面运行服务器
[1] 6968
$ ./client             //运行客户端
please input less then 8 chars for using. 
hello 
[client] sending data (hello )to server by socket      //成功发送数据
[server] receiving data (hello) from client by socket  //成功接收数据

$ ./client            //再次运行客户端
please input less then 8 chars for using. 
socket
[client] sending data (socket )to server by socket  
[server] receiving data (socket) from client by socket

$ ./client            //最后一次运行客户端
please input less then 8 chars for using. 
good
[client] sending data (good )to server by socket  
[server] receiving data (good) from client by socket
[1]+  Done                    ./server      //服务器停止运行

看官们,从上面的运行结果中可以看到,客户端通过套接字发送数据给服务器,而服务器通过套接字接收客户端发来的数据,这样客户端和服务器端可以通过套接字进行通信。另外,我们进行了三次通信,通信的次数可以自己控制,甚至写成无限次也是可以的。每次通信可以看作是一个完整的通信过程,我们在通信过程中发送的数据是字符串,在三次通信中,我们发送了三个不同的字符串。

我们在前面说过,基于AF_UNIX域的套接字通信,本质上是通过文件进行的。接下来,我们验证一下。

文件的目录设定在了套接字的地址中:#define SOCKET_PATH “/tmp/SOCKET_TEST”

$ ll /tmp/
srwxr-xr-x  1 tom  tom      0  528 10:40 SOCKET_TEST=
//省略掉其它无关的信息

大家可以看到确实有一个名叫SOCKET_TEST的文件,而且该文件的类型为s,也就是套接字类型。

各位看官,关于基于AF_UNIX域的流套接字通信的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解 。