Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1808559
  • 博文数量: 272
  • 博客积分: 1272
  • 博客等级: 少尉
  • 技术积分: 1866
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-09 15:51
文章分类

全部博文(272)

文章存档

2016年(16)

2015年(28)

2014年(97)

2013年(59)

2012年(25)

2011年(47)

分类: LINUX

2013-08-19 13:52:58

socket进程通信与网络通信使用的是统一套接口,只是地址结构与某些参数不同。

一。创建socket服务端的流程如下:

(1)创建socket,类型为AF_LOCAL或AF_UNIX,表示用于进程通信: 
 

点击(此处)折叠或打开

  1. int server_fd;
  2. int client_fd;//client file descriptor
  3. struct sockaddr_un server_addr;
  4. struct sockaddr_un client_addr;
  5. size_t server_len,client_len;
  6.   
  7. //cteate server socket
  8. //delete old socket file
  9. unlink(SERVER_NAME);
  10. if ((server_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
  11.  perror("socket");
  12.   exit(1);
  13. }



(2)命名socket。这里面有一个很关键的东西,socket进程通信命名方式有两种。一是普通的命名,socket会根据此命名创建一个同名的socket文件,客户端连接的时候通过读取该socket文件连接到socket服务端。这种方式的弊端是服务端必须对socket文件的路径具备写权限,客户端必须知道socket文件路径,且必须对该路径有读权限。另外一种命名方式是抽象命名空间,这种方式不需要创建socket文件,只需要命名一个全局名字,即可让客户端根据此名字进行连接。后者的实现过程与前者的差别是,后者在对地址结构成员sun_path数组赋值的时候,必须把第一个字节置0,即sun_path[0] = 0,下面用代码说明:



第一种方式:


点击(此处)折叠或打开

  1. //name the server socket

  2. server_addr.sun_family = AF_UNIX;

  3. strcpy(server_addr.sun_path,SERVER_NAME);

  4. server_len = sizeof(struct sockaddr_un);

  5. client_len = server_len;


第二种方式:

点击(此处)折叠或打开

  1. //name the socket
  2. server_addr.sun_family = AF_UNIX;
  3. strcpy(server_addr.sun_path, SERVER_NAME);
  4. server_addr.sun_path[0]=0;
  5. //server_len = sizeof(server_addr);
  6. server_len = strlen(SERVER_NAME) + offsetof(struct sockaddr_un, sun_path);
其中,offsetof函数在#include 头文件中定义。因第二种方式的首字节置0,我们可以在命名字符串SERVER_NAME前添加一个占位字符串,例如:

 

#define SERVER_NAME @socket_server 


前面的@符号就表示占位符,不算为实际名称。 

 或者可以把第二种方式的实现封装成一个函数:


点击(此处)折叠或打开

  1. int makeAddr(const char* name, struct sockaddr_un* pAddr, socklen_t* pSockLen)
  2. {
  3.   int nameLen = strlen(name);
  4.   if (nameLen >= (int) sizeof(pAddr->sun_path) -1) /* too long? */
  5.        return -1;
  6.    pAddr->sun_path[0] = '\0'; /* abstract namespace */
  7.     strcpy(pAddr->sun_path+1, name);
  8.     pAddr->sun_family = AF_UNIX;
  9.    *pSockLen = 1 + nameLen + offsetof(struct sockaddr_un, sun_path);
  10.     return 0;

  11. }

 像下面这样使用这个函数:

 

makeAddr("server_socket", &server_addr, &server_len); 



提示:客户端连接服务器的时候,必须与服务端的命名方式相同,即如果服务端是普通命名方式,客户端的地址也必须是普通命名方式;如果服务端是抽象命名方式,客户端的地址也必须是抽象命名方式。


(3)绑定并侦听

  1. bind(server_sockfd, (struct sockaddr *)&server_addr, server_len); 
  2.  
  3. //listen the server 
  4. listen(server_sockfd, 5); 

 
(4)等待客户端连接,并读写数据。
  1. while(1){ 
  2. printf("server waiting...\n"); 
  3.  
  4. //accept client connect 
  5. client_len = sizeof(client_addr); 
  6. client_sockfd = accept(server_sockfd,(struct sockaddr*)&client_addr, &client_len); 
  7.  
  8. //read  data from client socket 
  9. read(client_sockfd, &ch, 1); 
  10. printf("read from client %d: %c",client_sockfd,ch); 
  11. ch ++; 
  12. write(client_sockfd, &ch, 1); 
  13. close(client_sockfd); 
  14. usleep(100);//1000 miliseconds = 1 second 
  15.   } 

 
二 socket客户端创建流程

 

(1)创建socket

(2)命名socket

(3)连接到服务端:

  1. //connect to server 
  2.     result = connect(sockfd, (struct sockaddr*)&address, len);  

     (4)与服务端进行通信
  1. //communicate with server socket 
  2. while(1) 
  3.     printf("set send content:"); 
  4.     scanf("%c",&ch); 
  5.     write(sockfd, &ch, 1); 
  6.     printf("send to server:%c \n",ch); 
  7.     read(sockfd, &ch, 1); 
  8.     printf("read from server: %c\n", ch); 
  9.      
  10.      



完整代码如下:


(1)服务端server.c:

  1. #include 
  2. #include 
  3. #include 
  4. #include 
  5. #include 
  6. #include 
  7. #include  
  8.  
  9. #define SERVER_NAME "@server_socket" 
  10. /*
  11. * Create a UNIX-domain socket address in the Linux "abstract namespace".
  12. *
  13. * The socket code doesn't require null termination on the filename, but
  14. * we do it anyway so string functions work.
  15. */ 
  16. int makeAddr(const char* name, struct sockaddr_un* pAddr, socklen_t* pSockLen) 
  17.     int nameLen = strlen(name); 
  18.     if (nameLen >= (int) sizeof(pAddr->sun_path) -1)  /* too long? */ 
  19.         return -1; 
  20.     pAddr->sun_path[0] = '\0'/* abstract namespace */ 
  21.     strcpy(pAddr->sun_path+1, name); 
  22.     pAddr->sun_family = AF_UNIX; 
  23.     *pSockLen = 1 + nameLen + offsetof(struct sockaddr_un, sun_path); 
  24.     return 0; 
  25.  
  26. int main() 
  27.  
  28.     int server_sockfd, client_sockfd; 
  29.     socklen_t server_len, client_len; 
  30.     struct sockaddr_un server_addr; 
  31.     struct sockaddr_un client_addr; 
  32.     char ch; 
  33.     int nread; 
  34.  
  35.     //delete the old server socket 
  36.     //unlink("server_socket"); 
  37.     //create socket 
  38.     server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0); 
  39.  
  40.     //name the socket 
  41.     server_addr.sun_family = AF_UNIX; 
  42.     strcpy(server_addr.sun_path, SERVER_NAME); 
  43.     server_addr.sun_path[0]=0; 
  44.     //server_len = sizeof(server_addr); 
  45.     server_len = strlen(SERVER_NAME)  + offsetof(struct sockaddr_un, sun_path); 
  46.     //makeAddr("server_socket", &server_addr, &server_len); 
  47.     bind(server_sockfd, (struct sockaddr *)&server_addr, server_len); 
  48.  
  49.     //listen the server 
  50.     listen(server_sockfd, 5); 
  51.     client_sockfd = -1; 
  52.     client_len = sizeof(client_addr); 
  53.     while(1){ 
  54.         printf("server waiting...\n"); 
  55.         //accept client connect 
  56.         if(client_sockfd == -1){ 
  57.             client_sockfd = accept(server_sockfd,(struct sockaddr*)&client_addr, &client_len); 
  58.         } 
  59.      
  60.         //read  data from client socket 
  61.         nread = read(client_sockfd, &ch, 1); 
  62.         if(nread == 0){//client disconnected 
  63.             printf("client %d disconnected\n",client_sockfd); 
  64.             client_sockfd = -1; 
  65.         } 
  66.         else
  67.             printf("read from client %d: %c\n",client_sockfd,ch); 
  68.             ch ++; 
  69.             write(client_sockfd, &ch, 1); 
  70.         } 
  71.         usleep(100);//1000 miliseconds = 1 second 
  72.     } 
  73.  
  74.     return 0; 
  75.  



(2)客户端client.c

 

  1. #include 
  2. #include 
  3. #include 
  4. #include 
  5. #include 
  6. #include 
  7. #include  
  8. #define SERVER_NAME "@server_socket" 
  9. /*
  10. * Create a UNIX-domain socket address in the Linux "abstract namespace".
  11. *
  12. * The socket code doesn't require null termination on the filename, but
  13. * we do it anyway so string functions work.
  14. */ 
  15. int makeAddr(const char* name, struct sockaddr_un* pAddr, socklen_t* pSockLen) 
  16.     int nameLen = strlen(name); 
  17.     if (nameLen >= (int) sizeof(pAddr->sun_path) -1)  /* too long? */ 
  18.         return -1; 
  19.     pAddr->sun_path[0] = '\0'/* abstract namespace */ 
  20.     strcpy(pAddr->sun_path+1, name); 
  21.     pAddr->sun_family = AF_UNIX; 
  22.     *pSockLen = 1 + nameLen + offsetof(struct sockaddr_un, sun_path); 
  23.     return 0; 
  24.  
  25.  
  26. int main() 
  27.     int sockfd; 
  28.     socklen_t len; 
  29.     struct sockaddr_un address; 
  30.     int result; 
  31.     char ch = 'A'
  32.  
  33.     //create socket  
  34.     sockfd = socket(AF_UNIX, SOCK_STREAM, 0); 
  35.     //name the server socket 
  36.     //makeAddr("server_socket", &address, &len); 
  37.     address.sun_family = AF_UNIX; 
  38.     strcpy(address.sun_path, SERVER_NAME); 
  39.     address.sun_path[0]=0; 
  40.     //len = sizeof(address); 
  41.     len =  strlen(SERVER_NAME)  + offsetof(struct sockaddr_un, sun_path); 
  42.     //connect to server 
  43.     result = connect(sockfd, (struct sockaddr*)&address, len); 
  44.     if(result == -1) 
  45.     { 
  46.         perror("opps:client1"); 
  47.         exit(1); 
  48.     } 
  49.     //communicate with server socket 
  50.     while(1) 
  51.     { 
  52.         printf("set send content:"); 
  53.         scanf("%c",&ch); 
  54.         write(sockfd, &ch, 1); 
  55.         printf("send to server:%c \n",ch); 
  56.         read(sockfd, &ch, 1); 
  57.         printf("read from server: %c\n", ch); 
  58.          
  59.          
  60.     } 
  61.     exit(0); 
  62.  
阅读(1144) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~