Linux 进程间通信 socket

来源:互联网 发布:司法拍卖淘宝网怎么进 编辑:程序博客网 时间:2024/06/03 12:28

http://haibor1x.blog.163.com/blog/static/763407200751052458572/

一个linux UDP网络通讯的例子源代码(server、client方式)

服务器端代码


[cpp] view plaincopy
#include <stdio.h>  #include <stdlib.h>  #include <string.h>  #include <sys/types.h>  #include <netinet/in.h>  #include <sys/socket.h>  #include <arpa/inet.h>  #include <unistd.h>      int main(int argc, char *argv[])  {      int sock;      //sendto中使用的对方地址      struct sockaddr_in toAddr;      //在recvfrom中使用的对方主机地址      struct sockaddr_in fromAddr;          int recvLen;      unsigned int addrLen;      char recvBuffer[128];          sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);          if(sock < 0)      {          printf("创建套接字失败了.\r\n");          exit(0);      }          memset(&fromAddr, 0, sizeof(fromAddr));      fromAddr.sin_family = AF_INET;      fromAddr.sin_addr.s_addr = htonl(INADDR_ANY);      fromAddr.sin_port = htons(4000);          if(bind(sock, (struct sockaddr *)&fromAddr, sizeof(fromAddr)) < 0)      {          printf("bind() 函数使用失败了.\r\n");          close(sock);          exit(1);      }          while(1)      {          addrLen = sizeof(toAddr);          if((recvLen = recvfrom(sock, recvBuffer, 128, 0, (struct sockaddr *)&toAddr, &addrLen)) < 0)          {              printf("()recvfrom()函数使用失败了.\r\n");              close(sock);              exit(1);          }          if(sendto(sock, recvBuffer, recvLen, 0, (struct sockaddr *)&toAddr, sizeof(toAddr)) != recvLen)          {              printf("sendto fail\r\n");              close(sock);              exit(0);          }          return 0;      }  }  






客户端代码


[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include <sys/types.h>  
  5. #include <netinet/in.h>  
  6. #include <sys/socket.h>  
  7. #include <arpa/inet.h>  
  8. #include <unistd.h>  
  9.   
  10.   
  11. int main(int argc, char *argv[])  
  12. {  
  13.     if(argc < 2)  
  14.     {  
  15.         printf("请输入要传送的内容.\r\n");  
  16.         exit(0);  
  17.     }  
  18.     int sock;  
  19.     //sendto中使用的对方地址  
  20.     struct sockaddr_in toAddr;  
  21.     //在recvfrom中使用的对方主机地址  
  22.     struct sockaddr_in fromAddr;  
  23.   
  24.   
  25.     unsigned int fromLen;  
  26.     char recvBuffer[128];  
  27.     sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);  
  28.   
  29.   
  30.     if(sock < 0)  
  31.     {  
  32.         printf("创建套接字失败了.\r\n");  
  33.         exit(1);  
  34.     }  
  35.   
  36.   
  37.     memset(&toAddr, 0, sizeof(toAddr));  
  38.     toAddr.sin_family = AF_INET;  
  39.     toAddr.sin_addr.s_addr = inet_addr("127.0.0.1");  
  40.     toAddr.sin_port = htons(4000);  
  41.   
  42.   
  43.     if(sendto(sock, argv[1], strlen(argv[1]), 0, (struct sockaddr *)&toAddr, sizeof(toAddr)) != strlen(argv[1]))  
  44.     {  
  45.         printf("sendto() 函数使用失败了.\r\n");  
  46.         close(sock);  
  47.         exit(1);  
  48.     }  
  49.   
  50.   
  51.     fromLen = sizeof(fromAddr);  
  52.     if(recvfrom(sock, recvBuffer, 128, 0, (struct sockaddr *)&fromAddr, &fromLen) < 0)  
  53.     {  
  54.         printf("()recvfrom()函数使用失败了.\r\n");  
  55.         close(sock);  
  56.         exit(1);  
  57.     }  
  58.     printf("recvfrom() result:%s\r\n", recvBuffer);  
  59.     close(sock);  
  60.     return 0;  
  61. }  






http://bbs.csdn.net/topics/310080001

Linux 进程间通信 事例

用于进程间通信的socket主要是指unix domain socket; 它用到这样一个地址结构
          struct sockaddr_un; 这个结构在<sys/un.h>头文件中;有两个主要成员
          sun_family和sun_path; sun_family可以是AF_UNIX或者AF_LOCALE;sun_path是一个文件名,一般用绝对路径; 这儿给个用unix domain socket的小例子;这个例子用的就是UDP形式;直接上代码

//header.h

C/C++ code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <signal.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/un.h> //for unix domain socket
#include <pthread.h>
 
 
#define BUFSIZE 1024
#define SERVPORT 5000
 
//for unix domain socket
#define SOCKET_PATH  "/tmp/serverpath"
//error
#ifdef __cplusplus
extern "C" {
#endif
 
void error(const char *fmt,...){
    char buf[BUFSIZE];
    va_list ptr;
    memset(buf,0,BUFSIZE);
     
    va_start(ptr,fmt);
    vsnprintf(buf,BUFSIZE,fmt,ptr);
    va_end(ptr);
     
    fprintf(stderr,"%s\n",buf);
    exit(EXIT_FAILURE);
}
#ifdef __cplusplus
}
#endif


//unixdomain.c 服务端
C/C++ code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/*
    unix domain socket: designed for interprocess communication 
    key system calls: socket/bind/connect/listen/accept
    key structure: struct sockaddr_un 
     
    Author: hittlle
    purpose: Demo of UNIX Domain Socket
    Program Name: DomainServer
*/
 
#include "header.h"
 
int main(int argc, char **argv){
     
    int listenFd, clientFd;
    struct sockaddr_un servAddr, clientAddr;
    socklen_t socklen;
 
    char buf[BUFSIZE];
 
    bzero(buf, BUFSIZE);
    bzero(&servAddr, sizeof(servAddr));
 
    //set address 
    servAddr.sun_family = AF_UNIX;//AF_LOCALE is also OK
    strcpy(servAddr.sun_path, SOCKET_PATH);
 
    unlink(SOCKET_PATH);   
    if((listenFd = socket(AF_UNIX, SOCK_DGRAM,0)) < 0)
        error("%s"strerror(errno));
     
    if(bind(listenFd, (struct sockaddr*)&servAddr,sizeof(servAddr)) < 0){
        close(listenFd);
        error("%s"strerror(errno));
    }
     
    while(1){
        if(recvfrom(listenFd,buf,BUFSIZE,0,(struct sockaddr*)&clientAddr,&socklen) > 0)
            write(STDOUT_FILENO,buf,sizeof(buf));
    }
     
    return 0;
}


//unixclient.c 客户端
C/C++ code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include "header.h"
 
int main(int argc, char **argv){
     
    int sockfd;
    struct sockaddr_un servaddr;
    socklen_t socklen = sizeof(struct sockaddr_un);
    char buf[BUFSIZE] = "This is a test message here......Demo of Domain Socket\n";
 
    bzero(&servaddr, sizeof(servaddr));
     
    servaddr.sun_family = AF_UNIX;
    strcpy(servaddr.sun_path, SOCKET_PATH);
     
    if((sockfd = socket(AF_UNIX,SOCK_DGRAM,0)) < 0)
        error("%s"strerror(errno));
     
     
    sendto(sockfd,buf,sizeof(buf),0, (struct sockaddr*)&servaddr,socklen);
     
    close(sockfd);
     
    return 0;
}
 
 
这只是一个小例子,别拍砖

用于进程间通信的socket主要是指unix domain socket; 它用到这样一个地址结构
  struct sockaddr_un; 这个结构在<sys/un.h>头文件中;有两个主要成员
  sun_family和sun_path; sun_family可以是AF_UNIX或者AF_LOCALE;sun_path是一个文件名,一般用绝对路径; 

主要是这个数据结构的sun_path,填对了就ok






http://www.iteye.com/topic/1113587

Linux下Socket通信(IPC)

1、Linux下的Socket通信是一种基于文件的IPC通信,也可以是基于其他设备的IPC通信。它可以在本机内不同进程间实现通信,也可以在实现不同主机之间的通信。

2、Socket是一种进程间通信模式:
对等模式(P2P):一对一:UDP
客户服务器模式(C/S):一对多:TCP

3、基本创建步骤
(1)通过socket()函数创建socket
(2)通过bind函数绑定socket于设备地址
(3)进行读写操作read/recv/recvfrom write/send/sendto
(4)close方法关闭套接字

4、下面是其中用到的一些函数的用法及说明
(1)socket函数
int socket(int domain,int type, int protocol)
domain:地址族 IF_INET与底层内核通信(原生数据包)
type:通信的数据格式
protocol:传递数的含义

通信的数据类型:
SOCK_STREAM:字节流(一对多)
SOCK_DGRAM:字节包(一对一)
SOCK_RAW:硬件层的原生数据包  

通信的协议:
0:默认协议:地址族+数据格式=唯一决定协议
指定协议 IPPROTO_TCP
        IPPROTO_UDP 
        IPPROTO_IP
        IPPROTO_ICMP
        IPPROTO_IGMP

(2)bind函数
把socket绑定到一个通信地址
int bind(int sockfd,const struct sockaddr* addr,socklen_t len)
sockfd:绑定地址的socket
addr:地址
len:地址内存长度
返回:成功是0,失败是-1

(3)recvfrom函数
如果想返回数据发送者的地址,则使用recvfrom.
int recvfrom(int fd,
 void *buf,
 size_t len,
 int flag,
 struct sockaddr*addr,//返回数据发送者的地址) ssocklen_t *l);//输入返回地址缓冲长度,返回实际发送者的地址长度

(4)write/send/sendto函数
int sendto(int fd,//发送socket
    const void *buf,//发送的数据
    size_t len,//发送数据的长度
    int flag,//发送数据的方式,建议为0
    const struct sockaddr *addr,//数据        发往的目的地址
    socklen_t l);//地址长度
  返回:
    -1:发送失败
    否则就是发送的字节数。

 

代码如下:

test1.c

C代码  收藏代码
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <unistd.h>  
  4. #include <netinet/in.h>  
  5. #include <arpa/inet.h>  
  6.   
  7. int main(void)  
  8. {  
  9.     //create socket  
  10.     int fd = socket(AF_INET, SOCK_DGRAM, 0);  
  11.     if(fd==-1)  
  12.     {  
  13.         perror("socket\n");  
  14.         exit(-1);  
  15.     }  
  16.     printf("socket fd=%d\n",fd);  
  17.   
  18.     //build connection address  
  19.     struct sockaddr_in addr;  
  20.     addr.sin_family = AF_INET;  
  21.     addr.sin_port = htons(6666);  
  22.     addr.sin_addr.s_addr = inet_addr("127.0.0.1");  
  23.   
  24.     int r;  
  25.     r = bind(fd,(struct sockaddr*)&addr,sizeof(addr));  
  26.     if(r==-1)  
  27.     {  
  28.         perror("bind");  
  29.         close(fd);  
  30.         exit(-1);  
  31.     }  
  32.     printf("bind address successful!\n");  
  33.     //accept or send message  
  34.     char buf[255];  
  35.     struct sockaddr_in from;  
  36.     socklen_t len;  
  37.     len = sizeof(from);  
  38.     while(1)  
  39.     {  
  40.         r = recvfrom(fd,buf,sizeof(buf)-1,0,(struct sockaddr*)&from,&len);  
  41.         if(r>0)  
  42.         {  
  43.             buf[r]=0;  
  44.             printf("The message from %s is:%s\n",inet_ntoa(from.sin_addr),buf);  
  45.         }  
  46.         else  
  47.         {  
  48.             break;  
  49.         }  
  50.     }  
  51.     //close socket  
  52.     close(fd);  
  53.     return 0;  
  54. }  

test2.c

Java代码  收藏代码
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <unistd.h>  
  4. #include <string.h>  
  5. #include <sys/socket.h>  
  6. #include <netinet/in.h>  
  7. #include <arpa/inet.h>  
  8.   
  9. int main(void)  
  10. {  
  11.     //create socket  
  12.     int fd = socket(AF_INET,SOCK_DGRAM,0);  
  13.     if(fd==-1)  
  14.     {  
  15.         perror("socket");  
  16.         exit(-1);  
  17.     }  
  18.     printf("create socket OK!\n");  
  19.     //create an send address  
  20.     struct sockaddr_in addr={};  
  21.     addr.sin_family = AF_INET;  
  22.     addr.sin_port = htons(6666);  
  23.     addr.sin_addr.s_addr=inet_addr("127.0.0.1");  
  24.     //send the message to the specify address  
  25.     int r;  
  26.     char buf[255];  
  27.     while(1)  
  28.     {  
  29.         r = read(0,buf,sizeof(buf)-1);  
  30.         if(r<=0)  
  31.             break;  
  32.         sendto(fd,buf,r,0,(struct sockaddr*)&addr,sizeof(addr));  
  33.     }  
  34.     //close socket  
  35.     close(fd);  
  36.     return 0;  
  37. }  

 运行结果如下:(先运行test1.o,然后运行test2.o,在test2.c运行后输入内容,在test1.c所在终端中就会显示信息)



 







http://www.ibm.com/developerworks/cn/linux/l-socket-ipc/

在 Linux 上实现基于 Socket 的多进程实时通信


套接口(Socket)为目前Linux上最为广泛使用的一种的进程间通信机制,与其他的Linux通信机制不同之处在于除了它可用于单机内的进程间通信以外,还可用于不同机器之间的进程间通信。但是由于Socket本身不支持同时等待和超时处理,所以它不能直接用来多进程之间的相互实时通信。

本文提出一个基于Socket的多进程之间通信的实现方法。原理是建立一个进程专门用来做为通信服务器(server)来中转各个进程之间的通信。它首先启动一个用来监视连接要求的listening Socket,并把它的描述(Descriptor)号加入到一个事先定义好的fd_set的集合中,这个fd_set的集合用来存放listening Socket和后来生成的通信Socket的描述号。Server运用system call select来实时检查是否有数据到达这个集合中的任何一个socket,如果有数据到达listening Socket,则这一定是客户端发起的连接请求,于是生成一个新的通信Socket与该客户端连接,将生成的Socket描述号加入到fd_set的集合中,将客户端的ID号和与之对应的Socket的描述号记录在ID登记表中。如果有数据到达某个通信Socket,则这一定是某个客户端发起的通信请求,读出数据并取出收信客户端ID号,在ID登记表中找到与之对应的Socket描述号,将数据通过对应Socket传送到收信客户端。

其他各进程作为客户端(client)。客户端的动作是首先建立通信Socket连接服务器端,然后通过通信Socket进行送信和收信。

下面给出具体的程序实现和说明,

首先给出Server端的程序,在这里假设有两个客户端要进行实时通信,ClientA向ClientB发送字符1,ClientB向ClientA发送字符2。

  #include  <sys/types.h>#include <sys/socket.h>#include <stdio.h>#include <sys/un.h>#include <sys/time.h>#include <sys/ioctl.h>#include <unistd.h>#include <netinet/in.h>int main(){  int        rcd ;  struct sockaddr_un  server_sockaddr ;  int        backlog ;  ushort        ci ;  int        watch_fd_list[3] ;  fd_set        catch_fd_set ;  fd_set        watchset ;  int    new_cli_fd ;  int   maxfd;  int    socklen ,server_len;  struct sockaddr_un  cli_sockaddr ;  struct {    char  module_id ;  /* Module ID    */    int  cli_sock_fd ;  /* Socket ID    */  } cli_info_t[2] ;    for (ci=0;ci<=1;ci++)    cli_info_t[ci].cli_sock_fd=-1;      for (ci=0;ci<=2;ci++)    watch_fd_list[ci]=-1;        int server_sockfd,client_sockfd;    server_sockfd = socket( AF_UNIX, SOCK_STREAM, 0 ) ;  server_sockaddr.sun_family = AF_UNIX ;  strcpy( server_sockaddr.sun_path, "server_socket" ) ;  server_len=sizeof(server_sockaddr);  rcd = bind( server_sockfd, ( struct sockaddr * )&server_sockaddr, server_len ) ;    backlog = 5 ;  rcd = listen( server_sockfd, backlog ) ;  printf("SERVER::Server is  waitting on socket=%d \n",server_sockfd);  watch_fd_list[0]=server_sockfd;  FD_ZERO( &watchset ) ;  FD_SET( server_sockfd, &watchset ) ;  maxfd=watch_fd_list[0];

在上面的程序中,Server生成listening Socket(server_sockfd),初始化Socket监视集合(watchset),并将listening Socket放入Socket监视集合中。

while (1){char ch;int fd;int nread;catch_fd_set=watchset;rcd = select( maxfd+1, &catch_fd_set, NULL, NULL, (struct timeval *)0 ) ;

在上面的程序中,Server运用系统调用函数 select来实时检查是否有数据到达Socket监视集合中的任何一个socket。

        if ( rcd < 0 ) {      printf("SERVER::Server 5 \n");      exit(1);    }    if ( FD_ISSET( server_sockfd, &catch_fd_set ) ) {      socklen = sizeof( cli_sockaddr ) ;      new_cli_fd = accept( server_sockfd, ( struct sockaddr * )        &( cli_sockaddr ), &socklen ) ;      printf(" SERVER::open communication with  Client %s on socket %d\n",            cli_sockaddr.sun_path,new_cli_fd);          for (ci=1;ci<=2;ci++){        if(watch_fd_list[ci] != -1) continue;        else{            watch_fd_list[ci] = new_cli_fd;          break;        }        }        FD_SET(new_cli_fd , &watchset ) ;      if ( maxfd < new_cli_fd ) {        maxfd = new_cli_fd ;      }            for ( ci=0;ci<=1;ci++){        if(cli_info_t[ci].cli_sock_fd == -1) {          cli_info_t[ci].module_id=cli_sockaddr.sun_path[0];          cli_info_t[ci].cli_sock_fd=new_cli_fd;          break;        }          }              continue;      }

在上面的程序中,Server运用系统调用函数FD_ISSET来检查是否有客户端的连接请求到达Listening Socket, 如果返回值大于0,Server生成一个新的通信Socket (new_cli_fd)与客户端连接。将新生成的通信Socket放入Socket监视集合中(FD_SET)。将客户端的信息(ID号和Socket描述号)保存在注册表cli_info_t中

    for ( ci = 1; ci<=2 ; ci++ ) {      int      dst_fd = -1 ;      char      dst_module_id;      char       src_module_id;      int    i;      if (watch_fd_list[ ci ]==-1) continue;      if ( !FD_ISSET( watch_fd_list[ ci ], &catch_fd_set ) ) {        continue ;      }      ioctl(watch_fd_list[ ci ],FIONREAD,&nread);      if (nread==0){        continue;      }        read( watch_fd_list[ ci ], &dst_module_id, 1 ) ;      for (i=0;i<=1;i++){        if(cli_info_t[i].module_id == dst_module_id)           dst_fd=  cli_info_t[i].cli_sock_fd;           if(cli_info_t[i].cli_sock_fd==watch_fd_list[ ci ])         src_module_id=  cli_info_t[i].module_id;          }      read( watch_fd_list[ ci ], &ch, 1 ) ;      printf("SERVER::char=%c to  Client %c on socket%d\n",ch, dst_module_id,dst_fd);        write(dst_fd,&src_module_id, 1 ) ;      write(dst_fd,&ch, 1 ) ;    }  }  }

在上面的程序中,如果有数据到达某个通信Socket,Server则读出数据并取出收信客户端ID号。在ID登记表中找到收信客户端对应的Socket描述号。并将数据通过对应Socket传送到收信客户端

给出客户端 ClientA的程序

ClientB的程序只需将 char dst_module_id='B'; 改为char dst_module_id='A'; char ch='1'; 改为char char ch='2';既可。

#include  <sys/types.h>#include <sys/socket.h>#include <stdio.h>#include <sys/un.h>#include <unistd.h>#include <netinet/in.h>#include <arpa/inet.h>int main(){int client_sockfd;int len;struct sockaddr_un server_sockaddr,cli_sockaddr;int result;char dst_module_id='B';char ch='1';char src_module_id;client_sockfd= socket(AF_UNIX,SOCK_STREAM,0);cli_sockaddr.sun_family = AF_UNIX ;strcpy( cli_sockaddr.sun_path, "A" ) ;bind(client_sockfd,(struct sockaddr * )&cli_sockaddr, sizeof( cli_sockaddr ) ) ;server_sockaddr.sun_family=AF_UNIX;strcpy( server_sockaddr.sun_path, "server_socket" ) ;len=sizeof(server_sockaddr);result = connect(client_sockfd,( struct sockaddr * )&server_sockaddr,len);if (result <0){printf("ClientA::error on connecting \n");exit(1);}printf("ClientA::succeed in connecting with server\n");sleep(10);write(client_sockfd,&dst_module_id,1);write(client_sockfd,&ch,1); read (client_sockfd,&src_module_id,1); read (client_sockfd,&ch,1); printf("ClientA::char from  Client %c =%c\n", src_module_id,ch);close (client_sockfd);}

下面是样本程序的执行结果

[root@zhou test]# ./server &[3] 4301[root@zhou test]# SERVER::Server is  waitting on socket=3./clientA & ./clientB &[4] 4302[5] 4303ClientA::succeed in connecting with server SERVER::open communication with  Client A on socket 4[root@zhou test]#  SERVER::open communication with  Client B on socket 5ClientB::succeed in connecting with serverSERVER::char=1 to  Client B on socket5ClientB::char from  Client A =1SERVER::char=2 to  Client A on socket4ClientA::char from  Client B =2

程序清单下载:server.c, clientA.c






http://blog.csdn.net/xnwyd/article/details/7359506

linux socket进程通信





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

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

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

[cpp] view plaincopy
  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,下面用代码说明:

第一种方式:

[cpp] view plaincopy
  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;  


第二种方式:

[cpp] view plaincopy
  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 <stddef.h>头文件中定义。因第二种方式的首字节置0,我们可以在命名字符串SERVER_NAME前添加一个占位字符串,例如:

[cpp] view plaincopy
  1. #define SERVER_NAME @socket_server  
前面的@符号就表示占位符,不算为实际名称。


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

[cpp] view plaincopy
  1. int makeAddr(const char* name, struct sockaddr_un* pAddr, socklen_t* pSockLen)  
  2. {  
  3.     int nameLen = strlen(name);  
  4.     if (nameLen >= (intsizeof(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. }  

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

[cpp] view plaincopy
  1. makeAddr("server_socket", &server_addr, &server_len);  

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

(3)绑定并侦听

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

(4)等待客户端连接,并读写数据。

[cpp] view plaincopy
  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)连接到服务端:

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

(4)与服务端进行通信

[cpp] view plaincopy
  1. //communicate with server socket  
  2. while(1)  
  3. {  
  4.     printf("set send content:");  
  5.     scanf("%c",&ch);  
  6.     write(sockfd, &ch, 1);  
  7.     printf("send to server:%c \n",ch);  
  8.     read(sockfd, &ch, 1);  
  9.     printf("read from server: %c\n", ch);  
  10.       
  11.       
  12. }  

完整代码如下:

(1)服务端server.c:

[cpp] view plaincopy
  1. #include<sys/types.h>  
  2. #include<sys/socket.h>  
  3. #include<stdio.h>  
  4. #include<sys/un.h>  
  5. #include<unistd.h>  
  6. #include<stdlib.h>  
  7. #include <stddef.h>  
  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. {  
  18.     int nameLen = strlen(name);  
  19.     if (nameLen >= (intsizeof(pAddr->sun_path) -1)  /* too long? */  
  20.         return -1;  
  21.     pAddr->sun_path[0] = '\0';  /* abstract namespace */  
  22.     strcpy(pAddr->sun_path+1, name);  
  23.     pAddr->sun_family = AF_UNIX;  
  24.     *pSockLen = 1 + nameLen + offsetof(struct sockaddr_un, sun_path);  
  25.     return 0;  
  26. }  
  27.   
  28. int main()  
  29.   
  30. {  
  31.     int server_sockfd, client_sockfd;  
  32.     socklen_t server_len, client_len;  
  33.     struct sockaddr_un server_addr;  
  34.     struct sockaddr_un client_addr;  
  35.     char ch;  
  36.     int nread;  
  37.   
  38.     //delete the old server socket  
  39.     //unlink("server_socket");  
  40.     //create socket  
  41.     server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);  
  42.   
  43.     //name the socket  
  44.     server_addr.sun_family = AF_UNIX;  
  45.     strcpy(server_addr.sun_path, SERVER_NAME);  
  46.     server_addr.sun_path[0]=0;  
  47.     //server_len = sizeof(server_addr);  
  48.     server_len = strlen(SERVER_NAME)  + offsetof(struct sockaddr_un, sun_path);  
  49.     //makeAddr("server_socket", &server_addr, &server_len);  
  50.     bind(server_sockfd, (struct sockaddr *)&server_addr, server_len);  
  51.   
  52.     //listen the server  
  53.     listen(server_sockfd, 5);  
  54.     client_sockfd = -1;  
  55.     client_len = sizeof(client_addr);  
  56.     while(1){  
  57.         printf("server waiting...\n");  
  58.         //accept client connect  
  59.         if(client_sockfd == -1){  
  60.             client_sockfd = accept(server_sockfd,(struct sockaddr*)&client_addr, &client_len);  
  61.         }  
  62.       
  63.         //read  data from client socket  
  64.         nread = read(client_sockfd, &ch, 1);  
  65.         if(nread == 0){//client disconnected  
  66.             printf("client %d disconnected\n",client_sockfd);  
  67.             client_sockfd = -1;  
  68.         }  
  69.         else{  
  70.             printf("read from client %d: %c\n",client_sockfd,ch);  
  71.             ch ++;  
  72.             write(client_sockfd, &ch, 1);  
  73.         }  
  74.         usleep(100);//1000 miliseconds = 1 second  
  75.     }  
  76.   
  77.     return 0;  
  78.   
  79. }  

(2)客户端client.c

[cpp] view plaincopy
  1. #include<sys/types.h>  
  2. #include<sys/socket.h>  
  3. #include<stdio.h>  
  4. #include<sys/un.h>  
  5. #include<unistd.h>  
  6. #include<stdlib.h>  
  7. #include <stddef.h>  
  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. {  
  17.     int nameLen = strlen(name);  
  18.     if (nameLen >= (intsizeof(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.   
  27.   
  28. int main()  
  29. {  
  30.     int sockfd;  
  31.     socklen_t len;  
  32.     struct sockaddr_un address;  
  33.     int result;  
  34.     char ch = 'A';  
  35.   
  36.     //create socket   
  37.     sockfd = socket(AF_UNIX, SOCK_STREAM, 0);  
  38.     //name the server socket  
  39.     //makeAddr("server_socket", &address, &len);  
  40.     address.sun_family = AF_UNIX;  
  41.     strcpy(address.sun_path, SERVER_NAME);  
  42.     address.sun_path[0]=0;  
  43.     //len = sizeof(address);  
  44.     len =  strlen(SERVER_NAME)  + offsetof(struct sockaddr_un, sun_path);  
  45.     //connect to server  
  46.     result = connect(sockfd, (struct sockaddr*)&address, len);  
  47.     if(result == -1)  
  48.     {  
  49.         perror("opps:client1");  
  50.         exit(1);  
  51.     }  
  52.     //communicate with server socket  
  53.     while(1)  
  54.     {  
  55.         printf("set send content:");  
  56.         scanf("%c",&ch);  
  57.         write(sockfd, &ch, 1);  
  58.         printf("send to server:%c \n",ch);  
  59.         read(sockfd, &ch, 1);  
  60.         printf("read from server: %c\n", ch);  
  61.           
  62.           
  63.     }  
  64.     exit(0);  
  65.   
  66. }  



http://www.cnblogs.com/ladd/archive/2012/06/25/2560888.html

Linux 下socket通信终极指南(附TCP、UDP完整代码)

linux下用socket通信,有TCP、UDP两种协议,网上的很多教程把两个混在了一起,或者只讲其中一种。现在我把自己这两天研究的成果汇总下来,写了一个完整的,适合初学者参考,也方便自己以后查阅。

首先讲什么是socket,不喜欢理论的可以略过。

Berkeley套接字应用程序接口(API)包括了一个用C语言写成的应用程序开发库,主要用于实现进程间通讯,在计算机网络通讯方面被广泛使用。(来自 wikipedia socket )

下面介绍一下常用的socket API(也来自 wikipedia socket)

 

这个列表是一个Berkeley套接字API库提供的函数或者方法的概要:

  • socket() 创建一个新的确定类型的套接字,类型用一个整型数值标识,并为它分配系统资源。
  • bind() 一般用于服务器端,将一个套接字与一个套接字地址结构相关联,比如,一个指定的本地端口和IP地址。
  • listen() 用于服务器端,使一个绑定的TCP套接字进入监听状态。
  • connect() 用于客户端,为一个套接字分配一个自由的本地端口号。 如果是TCP套接字的话,它会试图获得一个新的TCP连接。
  • accept() 用于服务器端。 它接受一个从远端客户端发出的创建一个新的TCP连接的接入请求,创建一个新的套接字,与该连接相应的套接字地址相关联。
  • send()recv(),或者write()read(),或者recvfrom()sendto(), 用于往/从远程套接字发送和接受数据。
  • close() 用于系统释放分配给一个套接字的资源。 如果是TCP,连接会被中断。
  • gethostbyname()gethostbyaddr() 用于解析主机名和地址。
  • select() 用于修整有如下情况的套接字列表: 准备读,准备写或者是有错误。
  • poll() 用于检查套接字的状态。 套接字可以被测试,看是否可以写入、读取或是有错误。
  • getsockopt() 用于查询指定的套接字一个特定的套接字选项的当前值。
  • setsockopt() 用于为指定的套接字设定一个特定的套接字选项。

更多的细节如下给出。

[编辑]socket()

socket() 为通讯创建一个端点,为套接字返回一个文件描述符。 socket() 有三个参数:

  • domain 为创建的套接字指定协议集。 例如:
    • PF_INET 表示IPv4网络协议
    • PF_INET6 表示IPv6
    • PF_UNIX 表示本地套接字(使用一个文件)
  • type 如下:
    • SOCK_STREAM (可靠的面向流服务或流套接字)
    • SOCK_DGRAM (数据报文服务或者数据报文套接字)
    • SOCK_SEQPACKET (可靠的连续数据包服务)
    • SOCK_RAW (在网络层之上的原始协议)。
  • protocol 指定实际使用的传输协议。 最常见的就是IPPROTO_TCPIPPROTO_SCTPIPPROTO_UDPIPPROTO_DCCP。这些协议都在<netinet/in.h>中有详细说明。 如果该项为“0”的话,即根据选定的domain和type选择使用缺省协议。

如果发生错误,函数返回值为-1。 否则,函数会返回一个代表新分配的描述符的整数。

原型:
<span class="kw4" style="margin: 0px; padding: 0px;">int</span> socket<span class="br0" style="margin: 0px; padding: 0px;">(</span><span class="kw4" style="margin: 0px; padding: 0px;">int</span> domain<span class="sy0" style="margin: 0px; padding: 0px;">,</span> <span class="kw4" style="margin: 0px; padding: 0px;">int</span> type<span class="sy0" style="margin: 0px; padding: 0px;">,</span> <span class="kw4" style="margin: 0px; padding: 0px;">int</span> protocol<span class="br0" style="margin: 0px; padding: 0px;">)</span>。

[编辑]bind()

bind() 为一个套接字分配地址。当使用socket()创建套接字后,只赋予其所使用的协议,并未分配地址。在接受其它主机的连接前,必须先调用bind()为套接字分配一个地址。bind()有三个参数:

  • sockfd, 表示使用bind函数的套接字描述符
  • my_addr, 指向sockaddr结构(用于表示所分配地址)的指针
  • addrlen, 用socklen_t字段指定了sockaddr结构的长度

如果发生错误,函数返回值为-1,否则为0。

原型
<span class="kw4" style="margin: 0px; padding: 0px;">int</span> bind<span class="br0" style="margin: 0px; padding: 0px;">(</span><span class="kw4" style="margin: 0px; padding: 0px;">int</span> sockfd<span class="sy0" style="margin: 0px; padding: 0px;">,</span> <span class="kw4" style="margin: 0px; padding: 0px;">const</span> <span class="kw4" style="margin: 0px; padding: 0px;">struct</span> sockaddr <span class="sy0" style="margin: 0px; padding: 0px;">*</span>my_addr<span class="sy0" style="margin: 0px; padding: 0px;">,</span> socklen_t addrlen<span class="br0" style="margin: 0px; padding: 0px;">)</span><span class="sy0" style="margin: 0px; padding: 0px;">;</span>

[编辑]listen()

当socket和一个地址绑定之后,listen()函数会开始监听可能的连接请求。然而,这只能在有可靠数据流保证的时候使用,例如:数据类型(SOCK_STREAM,SOCK_SEQPACKET)。

listen()函数需要两个参数:

  • sockfd, 一个socket的描述符.
  • backlog, 一个决定监听队列大小的整数,当有一个连接请求到来,就会进入此监听队列,当队列满后,新的连接请求会返回错误。当请求被接受,返回 0。反之,错误返回 -1。

原型:

<span class="kw4" style="margin: 0px; padding: 0px;">int</span> listen<span class="br0" style="margin: 0px; padding: 0px;">(</span><span class="kw4" style="margin: 0px; padding: 0px;">int</span> sockfd<span class="sy0" style="margin: 0px; padding: 0px;">,</span> <span class="kw4" style="margin: 0px; padding: 0px;">int</span> backlog<span class="br0" style="margin: 0px; padding: 0px;">)</span><span class="sy0" style="margin: 0px; padding: 0px;">;</span>

[编辑]accept()

当应用程序监听来自其他主机的面对数据流的连接时,通过事件(比如Unix select()系统调用)通知它。必须用 accept()函数初始化连接。 Accept() 为每个连接创立新的套接字并从监听队列中移除这个连接。它使用如下参数:

  • sockfd,监听的套接字描述符
  • cliaddr, 指向sockaddr 结构体的指针,客户机地址信息。
  • addrlen,指向 socklen_t的指针,确定客户机地址结构体的大小 。

返回新的套接字描述符,出错返回-1。进一步的通信必须通过这个套接字。

Datagram 套接字不要求用accept()处理,因为接收方可能用监听套接字立即处理这个请求。

函数原型:
<span class="kw4" style="margin: 0px; padding: 0px;">int</span> accept<span class="br0" style="margin: 0px; padding: 0px;">(</span><span class="kw4" style="margin: 0px; padding: 0px;">int</span> sockfd<span class="sy0" style="margin: 0px; padding: 0px;">,</span> <span class="kw4" style="margin: 0px; padding: 0px;">struct</span> sockaddr <span class="sy0" style="margin: 0px; padding: 0px;">*</span>cliaddr<span class="sy0" style="margin: 0px; padding: 0px;">,</span> socklen_t <span class="sy0" style="margin: 0px; padding: 0px;">*</span>addrlen<span class="br0" style="margin: 0px; padding: 0px;">)</span><span class="sy0" style="margin: 0px; padding: 0px;">;</span>

[编辑]connect()

connect()系统调用为一个套接字设置连接,参数有文件描述符和主机地址。

某些类型的套接字是无连接的,大多数是UDP协议。对于这些套接字,连接时这样的:默认发送和接收数据的主机由给定的地址确定,可以使用 send()和 recv()。 返回-1表示出错,0表示成功。

函数原型:
<span class="kw4" style="margin: 0px; padding: 0px;">int</span> connect<span class="br0" style="margin: 0px; padding: 0px;">(</span><span class="kw4" style="margin: 0px; padding: 0px;">int</span> sockfd<span class="sy0" style="margin: 0px; padding: 0px;">,</span> <span class="kw4" style="margin: 0px; padding: 0px;">const</span> <span class="kw4" style="margin: 0px; padding: 0px;">struct</span> sockaddr <span class="sy0" style="margin: 0px; padding: 0px;">*</span>serv_addr<span class="sy0" style="margin: 0px; padding: 0px;">,</span> socklen_t addrlen<span class="br0" style="margin: 0px; padding: 0px;">)</span><span class="sy0" style="margin: 0px; padding: 0px;">;</span>

 

TCP socket通信

服务器端流程如下:

1.创建serverSocket

2.初始化 serverAddr(服务器地址)

3.将socket和serverAddr 绑定 bind

4.开始监听 listen

5.进入while循环,不断的accept接入的客户端socket,进行读写操作write和read

6.关闭serverSocket

客户端流程:

1.创建clientSocket

2.初始化 serverAddr

3.链接到服务器 connect

4.利用write和read 进行读写操作

5.关闭clientSocket

具体实现代码如下

 

[cpp] view plaincopy
  1. #server.c(TCP)  
[cpp] view plaincopy
  1. <pre name="code" class="cpp">#include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <sys/types.h>  
  4. #include <sys/socket.h>  
  5. #include <netinet/in.h>  
  6. #include <errno.h>  
  7. #define SRVPORT 10005  
  8. #define CONNECT_NUM 5  
  9. #define MAX_NUM 80  
  10. int main()  
  11. {  
  12.     int serverSock=-1,clientSock=-1;  
  13.     struct sockaddr_in serverAddr;  
  14.   
  15.     serverSock=socket(AF_INET,SOCK_STREAM,0);  
  16.     if(serverSock<0)  
  17.     {  
  18.         printf("socket creation failed\n");  
  19.         exit(-1);  
  20.     }  
  21.     printf("socket create successfully.\n");  
  22.   
  23.     memset(&serverAddr,0,sizeof(serverAddr));  
  24.     serverAddr.sin_family=AF_INET;  
  25.     serverAddr.sin_port=htons((u_short) SRVPORT);  
  26.     serverAddr.sin_addr.s_addr=htons(INADDR_ANY);  
  27.     if(bind(serverSock,&serverAddr,sizeof(struct sockaddr_in))==-1)  
  28.     {  
  29.         printf("Bind error.\n");  
  30.         exit(-1);  
  31.     }  
  32.     printf("Bind successful.\n");  
  33.   
  34.     if(listen(serverSock,10)==-1)  
  35.     {  
  36.         printf("Listen error!\n");  
  37.     }  
  38.     printf("Start to listen!\n");  
  39.   
  40.     char revBuf[MAX_NUM]={0};  
  41.     char sedBuf[MAX_NUM]={0};  
  42.     while(1)  
  43.     {  
  44.         clientSock=accept(serverSock,NULL,NULL);  
  45.         while(1)  
  46.         {  
  47.             if(read(clientSock,revBuf,MAX_NUM)==-1)  
  48.             {  
  49.                 printf("read error.\n");  
  50.             }  
  51.             else  
  52.             {  
  53.                 printf("Client:%s\n",revBuf);  
  54.             }  
  55.             if(strcmp(revBuf,"Quit")==0||strcmp(revBuf,"quit")==0)  
  56.             {  
  57.                 strcpy(sedBuf,"Goodbye,my dear client!");  
  58.             }  
  59.             else  
  60.             {  
  61.                 strcpy(sedBuf,"Hello Client.");  
  62.             }  
  63.             if(write(clientSock,sedBuf,sizeof(sedBuf))==-1)  
  64.             {  
  65.                 printf("Send error!\n");  
  66.             }  
  67.             printf("Me(Server):%s\n",sedBuf);  
  68.             if(strcmp(revBuf,"Quit")==0||strcmp(revBuf,"quit")==0)  
  69.             {  
  70.                 break;  
  71.             }  
  72.             bzero(revBuf,sizeof(revBuf));  
  73.             bzero(sedBuf,sizeof(sedBuf));  
  74.         }  
  75.         close(clientSock);  
  76.     }  
  77.     close(serverSock);  
  78.     return 0;  
  79. }</pre><br>  
  80. <pre></pre>  
  81. <pre name="code" class="cpp" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13px; line-height: 19px; background-color: rgb(245, 245, 245);"></pre><pre name="code" class="cpp" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13px; line-height: 19px; background-color: rgb(245, 245, 245);"></pre><pre name="code" class="cpp" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13px; line-height: 19px; background-color: rgb(245, 245, 245);"></pre><pre name="code" class="cpp" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13px; line-height: 19px; background-color: rgb(245, 245, 245);">#client.c(TCP)  
  82. </pre><pre name="code" class="cpp" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13px; line-height: 19px; background-color: rgb(245, 245, 245);"><pre name="code" class="cpp">#include <stdio.h>  
  83. #include <stdlib.h>  
  84. #include <sys/types.h>  
  85. #include <sys/socket.h>  
  86. #include <netinet/in.h>  
  87. #include <errno.h>  
  88. #include <string.h>  
  89. #define SRVPORT 10005  
  90. #define CONNECT_NUM 5  
  91. #define MAX_NUM 80  
  92. int main()  
  93. {  
  94.     int clientSock=-1;  
  95.     struct sockaddr_in serverAddr;  
  96.   
  97.     clientSock=socket(AF_INET,SOCK_STREAM,0);  
  98.     if(clientSock<0)  
  99.     {  
  100.         printf("socket creation failed\n");  
  101.         exit(-1);  
  102.     }  
  103.     printf("socket create successfully.\n");  
  104.   
  105.     memset(&serverAddr,0,sizeof(serverAddr));  
  106.     serverAddr.sin_family=AF_INET;  
  107.     serverAddr.sin_port=htons((u_short) SRVPORT);  
  108.     serverAddr.sin_addr.s_addr=htons(INADDR_ANY);  
  109.     if(connect(clientSock,&serverAddr,sizeof(struct sockaddr_in))<0)  
  110.     {  
  111.         printf("Connect error.\n");  
  112.         exit(-1);  
  113.     }  
  114.     printf("Connect successful.\n");  
  115.   
  116.     char sedBuf[MAX_NUM]={0};  
  117.     char revBuf[MAX_NUM]={0};  
  118.     while(gets(sedBuf)!=-1)  
  119.     {  
  120.         if(write(clientSock,sedBuf,strlen(sedBuf))==-1)  
  121.         {  
  122.             printf("send error!\n");  
  123.         }  
  124.         printf("Me(Client):%s\n",sedBuf);  
  125.         bzero(sedBuf,sizeof(sedBuf));  
  126.         if(read(clientSock,revBuf,MAX_NUM)==-1)  
  127.         {  
  128.             printf("rev error!\n");  
  129.         }  
  130.         printf("Sever:%s\n",revBuf);  
  131.         if(strcmp(revBuf,"Goodbye,my dear client!")==0)  
  132.             break;  
  133.         bzero(revBuf,sizeof(revBuf));  
  134.     }  
  135.     close(clientSock);  
  136.     return 0;  
  137. }  
  138. </pre><br>  
  139. <br>  
  140. <pre></pre>  
  141. <pre name="code" class="cpp" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13px; line-height: 19px; background-color: rgb(245, 245, 245);"></pre><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)"><span style="margin:0px; padding:0px">UDP协议不能保证数据通信的可靠性,但是开销更低,编起来也更加简单</span></p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)"> </p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">服务器流程:</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">1.创建serverSocket</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">2.设置服务器地址 serverAddr</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">3.将serverSocket和serverAddr绑定 bind</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">4.开始进行读写 sendto和recvfrom</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">5.关闭serverSocket</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">客户端流程</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">1.创建clientSocket</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">2.设置服务器地址 serverAddr</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">3.可选 设置clientAddr并和clientSocket(一般不用绑定)</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">4.进行发送操作 sendto</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">5.关闭clientSocket</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">具体代码如下:</p><p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)"> </p><pre name="code" class="cpp" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13px; line-height: 19px; background-color: rgb(245, 245, 245);">#server.c(UDP)  
  142. <pre name="code" class="cpp">#include <stdio.h>  
  143. #include <stdlib.h>  
  144. #include <unistd.h>  
  145. #include <netinet/in.h>//for sockaddr_in  
  146. #include <arpa/inet.h>//for socket  
  147. int main()  
  148. {  
  149.     int fd = socket(AF_INET, SOCK_DGRAM, 0);  
  150.     if(fd == -1)  
  151.     {  
  152.         perror("socket create error!\n");  
  153.         exit(-1);  
  154.     }  
  155.     printf("socket fd=%d\n", fd);  
  156.   
  157.   
  158.     struct sockaddr_in addr;  
  159.     addr.sin_family = AF_INET;  
  160.     addr.sin_port = htons(6666);  
  161.     addr.sin_addr.s_addr = inet_addr("127.0.0.1");  
  162.   
  163.   
  164.     int r;  
  165.     r = bind(fd, (struct sockaddr *)&addr, sizeof(addr));  
  166.     if(r == -1)  
  167.     {  
  168.         printf("Bind error!\n");  
  169.         close(fd);  
  170.         exit(-1);  
  171.     }  
  172.     printf("Bind successfully.\n");  
  173.   
  174.     char buf[255];  
  175.     struct sockaddr_in from;  
  176.     socklen_t len;  
  177.     len = sizeof(from);  
  178.     while(1)  
  179.     {  
  180.         r = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&from, &len);  
  181.         if(r > 0)  
  182.         {  
  183.             buf[r] = 0;  
  184.             printf("The message received for %s is :%s\n", inet_ntoa(from.sin_addr), buf);  
  185.         }  
  186.         else  
  187.         {  
  188.             break;  
  189.         }  
  190.     }  
  191.     close(fd);  
  192.     return 0;  
  193. }</pre><br>  
  194. <br>  
  195. <pre></pre>  
  196. <p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">  
  197.  </p>  
  198. <pre name="code" class="cpp" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-size: 13px; line-height: 19px; background-color: rgb(245, 245, 245);">#client.c(UDP)  
  199. <pre name="code" class="cpp">#include <stdio.h>  
  200. #include <stdlib.h>  
  201. #include <unistd.h>  
  202. #include <netinet/in.h>//for sockaddr_in  
  203. #include <arpa/inet.h>//for socket   
  204. int main()  
  205. {  
  206.     int fd = socket(AF_INET, SOCK_DGRAM, 0);  
  207.     if(fd == -1)  
  208.     {  
  209.         perror("socket create error!\n");  
  210.         exit(-1);  
  211.     }  
  212.     printf("socket fd=%d\n", fd);  
  213.   
  214.   
  215.     struct sockaddr_in addr_to;//目标服务器地址  
  216.     addr_to.sin_family = AF_INET;  
  217.     addr_to.sin_port = htons(6666);  
  218.     addr_to.sin_addr.s_addr = inet_addr("127.0.0.1");  
  219.   
  220.     struct sockaddr_in addr_from;  
  221.     addr_from.sin_family = AF_INET;  
  222.     addr_from.sin_port = htons(0); //获得任意空闲端口  
  223.     addr_from.sin_addr.s_addr = htons(INADDR_ANY); //获得本机地址  
  224.     r = bind(fd, (struct sockaddr *)&addr_from, sizeof(addr_from));  
  225.   
  226.     int r;  
  227.     if(r == -1)  
  228.     {  
  229.         printf("Bind error!\n");  
  230.         close(fd);  
  231.         exit(-1);  
  232.     }  
  233.     printf("Bind successfully.\n");  
  234.   
  235.   
  236.     char buf[255];  
  237.     int len;  
  238.     while(1)  
  239.     {  
  240.         r = read(0, buf, sizeof(buf));  
  241.         if(r < 0)  
  242.         {  
  243.             break;  
  244.         }  
  245.         len = sendto(fd, buf, r, 0, (struct sockaddr *)&addr_to, sizeof(addr_to));  
  246.         if(len == -1)  
  247.         {  
  248.             printf("send falure!\n");  
  249.         }  
  250.         else  
  251.         {  
  252.             printf("%d bytes have been sended successfully!\n", len);  
  253.         }  
  254.     }  
  255.     close(fd);  
  256.     return 0;  
  257. }</pre><br>  
  258. <br>  
  259. <pre></pre>  
  260. <p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">  
  261. <br style="margin:0px; padding:0px">  
  262. <span style="margin:0px; padding:0px">以上代码均经过测试(Ubuntu12.04),可以运行。有疑问,可以发电邮到ladd.cn@gmail.com</span></p>  
  263. <p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">  
  264.  </p>  
  265. <p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">  
  266. 参考文章</p>  
  267. <p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">  
  268. 1.wikipedia socket <a href="http://zh.wikipedia.org/wiki/Socket" style="margin:0px; padding:0px; color:rgb(0,105,214); line-height:inherit">http://zh.wikipedia.org/wiki/Socket</a></p>  
  269. <p style="margin:10px auto; padding-top:0px; padding-bottom:0px; font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:13px; line-height:19px; background-color:rgb(245,245,245)">  
  270. 2.TCP socket 之linux实现<a href="http://os.51cto.com/art/201001/179878.htm" style="margin:0px; padding:0px; color:rgb(0,105,214); line-height:inherit">http://os.51cto.com/art/201001/179878.htm</a></p>  
  271. <div style="top:8719px">  
  272. <p><span style="color:rgb(51,51,51); font-family:Helvetica,Tahoma,Arial,sans-serif; font-size:14px; line-height:24px"></span></p>  
  273. <p><span style="color:rgb(51,51,51); font-family:Helvetica,Tahoma,Arial,sans-serif; font-size:14px; line-height:24px"></span></p>  
  274. </div>  
  275. <pre></pre>  
  276. <pre></pre>  
  277. <pre></pre>  
  278. <pre></pre>  
  279.      
  280. </pre></pre></pre>  
0 0