linux高级编程之socket进程通信

Socket套接字不仅可以用于网络通信和局域网通信还可以用于本地的进程通信。
创建套接字时使用本地协议PF_UNIX,套接字分为流失套接字,数据报套接字。
Socket本地进程通信较其他的进程间通信方式(管道,system Ⅴ,BSD)使用更加方便、效率。
本地地址结构:
Struct  sockaddr_un   //<sys/un.h>
{
   Sa_family_t sun_family;
  Char sun_path[108]; //套接字的文件路径
}
填充地址结构:
1、定义:struct sockaddr_un myaddr;
2、置零:bzero(&myaddr,sizeof(myaddr));
3、配置:
myadd.sun_family=AF_UNIX;
strcpy(myadd.sun_path,”mysock”);//名字可以随意命名
一、UNIX域流式套接字服务器端的创建过程:
Socket(AF_UNIX,SOCK_STREAM,0)
Bind(,本地地址,)
Listen(,)
Accept(,,)
Recv()/send()
UNIX域流式套接字客户端的创建过程:
Socket(AF_UNIX,SOCK_STREAM,0)
Bind(,本地地址,)//可选
Connect(,,)
Recv()/send()
 ↓
…….
以下为创建的服务器端和客户端实现简单的进程间的通信:
服务器端:
      Server.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<errno.h>
#include<string.h>
#include<sys/un.h>
 
 
 
int main(int argc, const char *argv[])
{
     int n,sockfd,length,connfd;
     struct sockaddr_un  myaddr,clientaddr;
     char buf[128];
// 创建套接字
     sockfd=socket(PF_UNIX,SOCK_STREAM,0);
     if(sockfd<0)
     {
       perror("socket");
       return -1;
     }
//置零
     bzero(&myaddr,sizeof(myaddr));
//配置套接字
     myaddr.sun_family=AF_UNIX;
     strcpy(myaddr.sun_path,"mysocket");
//绑定套接字
     if((bind(sockfd,(struct sockaddr*)&myaddr,sizeof(myaddr)))<0)
         {
           perror("bind");
           return -1;
         }
//监听套接字
     if((listen(sockfd,10))<0)
     {
         perror("listen");
         return -1;
 
     }
     length=sizeof(clientaddr);
     while(1)
     {
         connfd=accept(sockfd,(struct sockaddr*)&clientaddr,&length);
          if(connfd<0)
          {
            perror("accept");
            return -1;
          }
          while((n=recv(connfd,buf,127,0))>0)
          {
              buf[n]='\0';
 
                 
          printf("receive:%s\n",buf);
          send(connfd,buf,strlen(buf),0);
          }
         
            if(strncmp(buf,"quit",4)==0)
            {
               break ;
            }
        close(connfd);    //关闭套接字
    }
    
    return 0;
}
客户端:
Client.c
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/un.h>
#include<sys/socket.h>
#include<string.h>
 
 
int main(int argc, const char *argv[])
{
 int n,sockfd,length;
char buf[128];
 struct sockaddr_un myaddr;
//创建套接字
   sockfd=socket(AF_UNIX,SOCK_STREAM,0);
 if(sockfd<0)
{
perror("socket");
return -1;
 }
//置零
bzero(&myaddr,sizeof(myaddr));
//配置套接字
myaddr.sun_family=AF_UNIX;
 strcpy(myaddr.sun_path,"mysocket");
//链接客户端
if (connect(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0)
 {
perror("connect");
exit(-1);
}
 do
{
fgets(buf,128,stdin);
length=strlen(buf)+1;
if (send(sockfd, buf, length, 0) < 0)
{
perror("send");
exit(-1);
}
memset(buf, 0, sizeof(buf));
length = recv(sockfd, buf, 128, 0);
if (length <= 0)
 {
break;
}
buf[length] = '\0';
printf("receive:%s\n", buf);
}
while(strncmp(buf,"quit",4)!=0);   //当输入quit时退出客户端
close(sockfd);//关闭套接字
 return 0;
}
编译执行后,效果如图所示:

 

 
二、UNIX域用户数据报套接字服务器端的创建过程:
UNIX域用户数据报套接字服务器的创建过程:、
Socket(AF_UNIX,SOCK_STREAM,0)
Bind(,本地地址,)//可选
                 Recvfrom()           ←
                         ↓                     ↑
Sendto()          ↑
↓      →        →  ↑
UNIX域用户数据报套接字客户端的创建过程:
Socket(AF_UNIX,SOCK_STREAM,0)
Bind(,本地地址,)//可选
Recvfrom()/sendto()
 ↓
……
客户端:
Server.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<errno.h>
#include<string.h>
#include<sys/un.h>
 
 
 
int main(int argc, const char *argv[])
{
     int n,sockfd;
     socklen_t slength;
     struct sockaddr_un  myaddr,clientaddr;
     char buf[128];
//创建套接字
     sockfd=socket(PF_UNIX,SOCK_DGRAM,0);
     if(sockfd<0)
     {
       perror("socket");
       return -1;
     }
//置零
     bzero(&myaddr,sizeof(myaddr));
  //配置套接字    
myaddr.sun_family=AF_UNIX;
     strcpy(myaddr.sun_path,"mysocket");
//绑定套接字
     if((bind(sockfd,(struct sockaddr*)&myaddr,sizeof(myaddr)))<0)
         {
           perror("bind");
           return -1;
         }
    
     slength=sizeof(clientaddr);
     while(1)
     {
         if((n=recvfrom(sockfd,buf,127,0,(struct sockaddr*)&clientaddr,&slength))>0)
         
          {
           buf[n]='\0';
          printf("receive:%s\n",buf);
          sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&clientaddr,sizeof(clientaddr));
          }
       if(strncmp(buf,"quit",4)==0)
            {
             break ;
            }     
    }
     close(sockfd);
    return 0;
}
客户端:
Client.c
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/un.h>
#include<sys/socket.h>
#include<string.h>
 
 
int main(int argc, const char *argv[])
{
    int n,m,sockfd,length;
    socklen_t slength;
    char buf[128];
struct sockaddr_un temp,myaddr;
//创建套接字
    sockfd=socket(AF_UNIX,SOCK_DGRAM,0);
    if(sockfd<0)
    {
      perror("socket");
      return -1;
   
    }
    //置零服务器套接字内存空间
   memset(&temp, 0, sizeof(temp));
//配置套接字
temp.sun_family = AF_UNIX;
strcpy(temp.sun_path, "mysocket");
//置零客户端套接字内存空间
    bzero(&myaddr,sizeof(myaddr));
    myaddr.sun_family=AF_UNIX;
strcpy(myaddr.sun_path,"mysock");
//绑定
    if((bind(sockfd,(struct sockaddr*)&myaddr,sizeof(myaddr)))<0)
    {
      perror("bind");
      return -1;
    }
    slength=sizeof(temp);
 
    do
    {
        fgets(buf,128,stdin);
        buf[strlen(buf)-1]=0;
        if (sendto(sockfd, buf, strlen(buf)+1, 0,(struct sockaddr*)&temp,sizeof(temp)) < 0)
        {
                     perror("send");
                     exit(-1);
}
memset(buf, 0, sizeof(buf));
       
length = recvfrom(sockfd,buf,128,0,(struct sockaddr*)&temp,&slength);
              if (length  <= 0)
        {
                     break;
              }
              buf[length] = '\0';
              printf("receive:%s\n", buf);
   
    }while(strncmp(buf,"quit",4)!=0);
    close(sockfd);
    return 0;
}
执行后:

 

总结:
看似unix的流式套接字和用户数据报套接字的区别不大,但是在实际操作的过程中,却有着非常大的区别,在本文中,unix用户数据报套接字在客户端中再次绑定了和设置了一个套接字,这样做的目的在于如果不创建这个套接字,服务器发送给客户端时由于是UDP协议没有确定的地址,导致服务器无法找到接受的那个客户端以至于无法发送信息过去。
posted @ 2016-08-31 19:39  Angst  阅读(274)  评论(0编辑  收藏  举报