Linux进程间通信——使用流套接字

2019-09-23 09:09:55王冬梅

4、接受连接——accept系统调用

该系统调用用来等待客户建立对该套接字的连接。accept系统调用只有当客户程序试图连接到由socket参数指定的套接字上时才返回,也就是说,如果套接字队列中没有未处理的连接,accept将阻塞直到有客户建立连接为止。accept函数将创建一个新套接字来与该客户进行通信,并且返回新套接字的描述符,新套接字的类型和服务器监听套接字类型是一样的。它的原型如下:

int accept(int socket, struct sockaddr *address, size_t *address_len); 

address为连接客户端的地址,参数address_len指定客户结构的长度,如果客户地址的长度超过这个值,它将会截断。

5、请求连接——connect系统调用

该系统调用用来让客户程序通过在一个未命名套接字和服务器监听套接字之间建立连接的方法来连接到服务器。它的原型如下:

int connect(int socket, const struct sockaddr *address, size_t address_len); 

参数socket指定的套接字连接到参数addres指定的服务器套接字。成功时返回0,失败时返回-1.

6、关闭socket——close系统调用

该系统调用用来终止服务器和客户上的套接字连接,我们应该总是在连接的两端(服务器和客户)关闭套接字。

六、进程使用流式socket进行通信

下面用多个客户程序和一个服务器程序来展示进程间如何利用套接字进行通信。

sockserver.c是一个服务器程序,它首先创建套接字,然后绑定一个端口再监听套接字,忽略子进程的停止消息等,然后它进入循环,一直循环检查是否有客户连接到服务器,如果有,则调用fork创建一个子进程来处理请求。利用read系统调用来读取客户端发来的信息,利用write系统调用来向客户端发送信息。这个服务器的工作非常简单,就是把客户发过来的字符+1,再发送回给客户。

sockclient.c是一个客户程序,它同样要先创建套接,然后连接到指定IP端口服务器,如果连接成功,就用write来发送信息给服务器,再用read获取服务器处理后的信息,再输出。

服务器sockserver.c的源代码如下:

#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <signal.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
  int server_sockfd = -1; 
  int client_sockfd = -1; 
  int client_len = 0; 
  struct sockaddr_in server_addr; 
  struct sockaddr_in client_addr; 
  //创建流套接字 
  server_sockfd = socket(AF_INET, SOCK_STREAM, 0); 
  //设置服务器接收的连接地址和监听的端口 
  server_addr.sin_family = AF_INET;//指定网络套接字 
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//接受所有IP地址的连接 
  server_addr.sin_port = htons(9736);//绑定到9736端口 
  //绑定(命名)套接字 
  bind(server_sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)); 
  //创建套接字队列,监听套接字 
  listen(server_sockfd, 5); 
  //忽略子进程停止或退出信号 
  signal(SIGCHLD, SIG_IGN); 

  while(1) 
  { 
    char ch = ''; 
    client_len = sizeof(client_addr); 
    printf("Server waitingn"); 
    //接受连接,创建新的套接字 
    client_sockfd = accept(server_sockfd, (struct sockaddr*)&client_addr, &client_len); 

    if(fork() == 0) 
    { 
      //子进程中,读取客户端发过来的信息,处理信息,再发送给客户端 
      read(client_sockfd, &ch, 1); 
      sleep(5); 
      ch++; 
      write(client_sockfd, &ch, 1); 
      close(client_sockfd); 
      exit(0); 
    } 
    else 
    { 
      //父进程中,关闭套接字 
      close(client_sockfd); 
    } 
  } 
}