socket unix domain socket

进程间通信有几种稳定、有效的的方式几乎被所有的操作系统采用:共享内存(Shared Memory)、管道(Pipe)、Unix Domain Socket和 RPC(Remote Procedure Calls 远程调用),本文主要介绍UDS和RPC.

Socket和HTTP的区别?

Socket是一个针对TCP和UDP编程的接口,你可以借助它建立TCP连接等等。而TCP和UDP协议属于传输层 。而http是个应用层的协议,它实际上也建立在TCP协议之上(HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力)。 

Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。Socket的出现只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象,从而形成了我们知道的一些最基本的函数接口。

Tip:顺便说下TCP和UDP的区别。TCP提供可靠的通信传输,类似于打电话,需要等待另一方的接听,才能进行真正的通讯;而UDP则不是可靠的,类似发短信,只将信息发出,至于对方有没收到,这个就不关心了。

socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIXDomain Socket。虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIX Domain Socket用于IPC更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。UNIX Domain Socket也提供面向流和面向数据包两种API接口,类似于TCP和UDP,但是面向消息的UNIX Domain Socket也是可靠的,消息既不会丢失也不会顺序错乱。

Unix Domain Socket,我们因为学习TCP/IP协议才接触到Socket。Socket在网络通信领域广泛应用 被称为Network Socket;Socket在同一机器上的进程间通信也是完全能够胜任的,但是执行效率不理想。因此出现了Unix Domain Socket专门针对单机内的进程间通信。(Network Socket与UDS的区别:前者是以TCP/IP协议栈为基础的,需要分包、重组等一系列操作,而后者的实现机制上不是依赖这些协议的)

UNIX Domain Socket是全双工的,API接口语义丰富,相比其它IPC机制有明显的优越性,目前已成为使用最广泛的IPC机制,比如X Window服务器和GUI程序之间就是通过UNIX Domain Socket通讯的。

使用UNIX Domain Socket的过程和网络socket十分相似,也要先调用socket()创建一个socket文件描述符,address family指定为AF_UNIX,type可以选择SOCK_DGRAM或SOCK_STREAM,protocol参数仍然指定为0即可。

UNIX Domain Socket与网络socket编程最明显的不同在于地址格式不同,用结构体sockaddr_un表示,网络编程的socket地址是IP地址加端口号,而UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径,这个socket文件由bind()调用创建,如果调用bind()时该文件已存在,则bind()错误返回。

mysql的主机和客户机在同一host(物理服务器)上的时候,mysql.sock就是使用unix domain socket做为通讯协议的载体,它比tcp快。

socket文件还在一般情况下通过socket文件是可以免密码登录的,所以以上的登录也可以这样直接登录。

       #"S"的选项和"--socket="是一样的
       mysql -S /tmp/mysql3307.sock

另外一个例子:

#include <sys/types.h>  
#include <sys/socket.h>  
#include <sys/un.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <stdio.h>  
  
int main()  
{  
  /* delete the socket file */  
  unlink("server_socket");  
    
  /* create a socket */  
  int server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);  
    
  struct sockaddr_un server_addr;  
  server_addr.sun_family = AF_UNIX;  
  strcpy(server_addr.sun_path, "server_socket");  
    
  /* bind with the local file */  
  bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));  
    
  /* listen */  
  listen(server_sockfd, 5);  
    
  char ch;  
  int client_sockfd;  
  struct sockaddr_un client_addr;  
  socklen_t len = sizeof(client_addr);  
  while(1)  
  {  
    printf("server waiting:\n");  
      
    /* accept a connection */  
    client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &len);  
      
    /* exchange data */  
    read(client_sockfd, &ch, 1);  
    printf("get char from client: %c\n", ch);  
    ++ch;  
    write(client_sockfd, &ch, 1);  
      
    /* close the socket */  
    close(client_sockfd);  
  }  
    
  return 0;  
}  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <sys/un.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <stdio.h>  
  
int main()  
{  
  /* create a socket */  
  int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);  
    
  struct sockaddr_un address;  
  address.sun_family = AF_UNIX;  
  strcpy(address.sun_path, "server_socket");  
    
  /* connect to the server */  
  int result = connect(sockfd, (struct sockaddr *)&address, sizeof(address));  
  if(result == -1)  
  {  
    perror("connect failed: ");  
    exit(1);  
  }  
    
  /* exchange data */  
  char ch = 'A';  
  write(sockfd, &ch, 1);  
  read(sockfd, &ch, 1);  
  printf("get char from server: %c\n", ch);  
    
  /* close the socket */  
  close(sockfd);  
    
  return 0;  
}  

我们调用socket函数创建一个socket:

int socket(int domain, int type, int protocol)

domain:指定socket所属的域,常用的是AF_UNIX或AF_INET

AF_UNIX表示以文件方式创建socket,AF_INET表示以端口方式创建socket(我们会在后面详细讲解AF_INET)

type:指定socket的类型,可以是SOCK_STREAM或SOCK_DGRAM

SOCK_STREAM表示创建一个有序的,可靠的,面向连接的socket,因此如果我们要使用TCP,就应该指定为SOCK_STREAM

SOCK_DGRAM表示创建一个不可靠的,无连接的socket,因此如果我们要使用UDP,就应该指定为SOCK_DGRAM

protocol:指定socket的协议类型,我们一般指定为0表示由第一第二两个参数自动选择。

socket()函数返回新创建的socket,出错则返回-1

2.地址格式:

常用的有两种socket域:AF_UNIX或AF_INET,因此就有两种地址格式:sockaddr_un和sockaddr_in,分别定义如下:

struct sockaddr_un  
{  
  sa_family_t sun_family;  /* AF_UNIX */  
  char sun_path[];         /* pathname */  
}  
  
  
struct sockaddr_in  
{  
  short int sin_family;          /* AF_INET */  
  unsigned short int sin_port;   /* port number */  
  struct in_addr sin_addr;       /* internet address */  
}  

struct in_addr  
{  
  unsigned long int s_addr;  
}  

从上面的定义我们可以看出,sun_path存放socket的本地文件名,sin_addr存放socket的ip地址,sin_port存放socket的端口号。

RPC
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

anssummer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值