zoukankan      html  css  js  c++  java
  • linux IPC socket(2)

    使用bind来关联地址和套接字

    #include <sys/types.h>
    #include <sys/socket.h>
    
    int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    返回值:成功0,出错-1
    sockfd:已经建立的socket描述符
    addr:指向sockaddr的结构体指针
    addrlen:addr结构的长度

    getsockname函数来发现绑定到套接字上的地址

    #include <sys/socket.h>
    
    int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    返回值:成功0,出错-1
    sockfd:已经建立的socket描述符
    addr:指向sockaddr的结构体指针
    addrlen:addr结构的长度

    如果套接字已经和对等方连接,可以调用getpeername函数来找到对方的地址

    #include <sys/socket.h>
    
    int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    返回值:成功0,出错-1
    sockfd:已经建立的socket描述符
    addr:指向sockaddr的结构体指针
    addrlen:addr结构的长度

    使用connect函数来建立连接

    #include <sys/types.h>
    #include <sys/socket.h>
    
    int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    返回值:成功0,出错-1
    sockfd:已经建立的socket描述符 
    addr:指向sockaddr的结构体指针
    addrlen:addr结构的长度

    服务器调用listen函数来宣告它愿意接收连接请求

    #include <sys/types.h>
    #include <sys/socket.h>
    
    int listen(int sockfd, int backlog);
    返回值:成功0,出错-1
    sockfd:已经建立的socket描述符
    backlog:等待连接队列的最大长度

    使用accept函数获取连接请求并建立连接

    #include <sys/types.h>
    #include <sys/socket.h>
    
    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    返回值:成功文件(套接字)描述符,出错-1
    sockfd:已经建立的socket描述符 
    addr:指向sockaddr的结构体指针
    addrlen:addr结构的长度

    send和write很像,但是可以指定标志来改变处理传输数据的方式

    #include <sys/types.h>
    #include <sys/socket.h>
    
    ssize_t send(int sockfd, const void *buf, size_t len, int flags);
    返回值:成功返回发送字节数,出错-1
    sockfd:socket描述符
    len:缓冲区数据长度
    flags:调用执行方式

    sendto可以在无连接的套接字上指定一个目标地址

    #include <sys/types.h>
    #include <sys/socket.h>
    
    ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
    返回值:成功发送的字节数,出错-1
    sockfd:socket描述符
    buf:带发送数据缓冲区
    len:缓冲区长度
    flags:调用方式标志位,一般为0
    dest_addr:指向目的套接字地址
    addrlen:所指地址长度

    可以调用带有msghdr结构的sendmsg来指定多重缓冲区传输数据,这和writev函数很相似

    #include <sys/types.h>
    #include <sys/socket.h>
    
    ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
    返回值:成功发送的字节数,出错-1
    sockfd:socket描述符
    msg:信息头结构指针
    flags:可选标记参数位,和send或是sendto参数相同

    msghdr结构

    struct msghdr {
                   void         *msg_name;       /* optional address */
                   socklen_t     msg_namelen;    /* size of address */
                   struct iovec *msg_iov;        /* scatter/gather array */
                   size_t        msg_iovlen;     /* # elements in msg_iov */
                   void         *msg_control;    /* ancillary data, see below */
                   size_t        msg_controllen; /* ancillary data buffer len */
                   int           msg_flags;      /* flags (unused) */
    };
    struct msghdr

    函数recv和read相似,但是recv可以指定标志来控制如何接收数据

    #include <sys/types.h>
    #include <sys/socket.h>
    
    ssize_t recv(int sockfd, void *buf, size_t len, int flags);
    返回值:数据字节长度,若无可用数据或对等方已经按序结束返回0,出错-1
    sockfd:socket描述符
    buf:接收数据缓冲
    len:buf的长度
    flags:可选标记位

    如果发送者已经调用shutdown来结束传输,或者网络协议支持按默认的顺序关闭并且发送端已经关闭,那么当所有的数据接收完毕后,recv会返回0

    如果兴趣定位发送者,可以使用recvfrom来得到数据发送者的源地址

    #include <sys/types.h>
    #include <sys/socket.h>
    
    ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
    返回值:返回数据字节长度,若无可用数据或对等方已经按序结束,返回0,出错-1
    sockfd:socket描述符
    buf:及诶手数据缓冲
    len:buf长度
    flags:可选标记位
    src_addr:如果非空,它将包含数据发送者的套接字端点地址
    addrlen:src_addr参数长度

    为了将数据送入多个缓冲区,或者想接收辅助数据,可以使用recvmsg

    #include <sys/types.h>
    #include <sys/socket.h>
    
    ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
    返回值:返回数据的自及诶长度,若无可用数据或对等方已经按序结束,返回0,出错-1
    sockfd:socket描述符
    msg:信息头结构指针
    flags:可选标志位

    可以使用setsockopt函数来设置套接字选项

    #include <sys/types.h>
    #include <sys/socket.h>
    
    int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
    返回值:成功0,失败-1
    sockfd:socket描述符
    level:标识了选项应用的协议
    optname:需要设置的选项
    optval:指向存放选项值的缓冲区指针
    optlen:optval的长度

    可以使用getsockopt函数来查看选项的当前值

    #include <sys/types.h>
    #include <sys/socket.h>
    
    int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
    返回值:成功0,失败-1
    sockfd:socket描述符
    level:标识了选项应用的协议
    optname:需要设置的选项
    optval:指向存放选项值的缓冲区指针
    optlen:指向optval缓冲区的长度

     TCP例程:

    服务器端:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <sys/types.h>
     4 #include <sys/socket.h>
     5 #include <netinet/in.h>
     6 #include <arpa/inet.h>
     7 #include <string.h>
     8 
     9 #define MAXLINE 80
    10 #define SERV_PORT 8000
    11 
    12 int main(void)
    13 {
    14         char buf[MAXLINE];
    15         int listenfd = 0;
    16 
    17         listenfd = socket(AF_INET, SOCK_STREAM, 0);
    18 
    19         struct sockaddr_in servaddr = {0};
    20         servaddr.sin_family = AF_INET;
    21         servaddr.sin_port = htons(SERV_PORT);
    22         servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    23 
    24         bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    25         listen(listenfd, 20);
    26 
    27         printf("Accepting connections ...
    ");
    28         while(1)
    29         {
    30                 struct sockaddr_in cliaddr = {0};
    31                 socklen_t cliaddr_len = sizeof(cliaddr);
    32                 int connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
    33 
    34                 char str[INET_ADDRSTRLEN];
    35                 printf("connect from %s at PORT %d
    ",
    36                                 inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
    37                                 ntohs(cliaddr.sin_port));
    38                 while(1)
    39                 {
    40                         int count = read(connfd, buf, MAXLINE);
    41                         if(count == 0)
    42                                 break;
    43 
    44                         write(connfd, buf, count);
    45                 }
    46                 close(connfd);
    47                 printf("closed from %s at PORT %d
    ",
    48                                 inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
    49                                 ntohs(cliaddr.sin_port));
    50         }
    51 }
    server.c

    客户端:

     1 #include <stdio.h>
     2 #include <arpa/inet.h>
     3 #include <stdlib.h>
     4 #include <unistd.h>
     5 #include <sys/socket.h>
     6 #include <netinet/in.h>
     7 
     8 #define MAXLINE 80
     9 #define SERV_PORT 8000
    10 #define MESSAGE "hello world"
    11 
    12 int main(int argc, char *argv[])
    13 {
    14         char buf[MAXLINE];
    15 
    16         int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    17 
    18         struct sockaddr_in servaddr = {0};
    19         servaddr.sin_family = AF_INET;
    20         inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
    21         servaddr.sin_port = htons(SERV_PORT);
    22 
    23         if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
    24         {
    25                 printf("connected failed");
    26                 return 1;
    27         }
    28 
    29         write(sockfd, MESSAGE, sizeof(MESSAGE));
    30         int count = read(sockfd, buf, MAXLINE);
    31 
    32         printf("Response from server: %s
    ", buf);
    33 
    34         close(sockfd);
    35         return 0;
    36 }
    client.c
    无欲速,无见小利。欲速,则不达;见小利,则大事不成。
  • 相关阅读:
    UVA10740 Not the Best (K短路)
    UVA10967 The Great Escape(最短路)
    UVA 10841 Lift Hopping in the Real World(dijkstra)
    U盘启动的PE系统的制作方法
    让远程桌面支持多用户
    学习的书的下载地址
    刚安装完的vs2008写的ajax应用提示sys未定义
    AS3 Libs
    禁用触发器
    Microsoft .NET 类库开发的设计准则
  • 原文地址:https://www.cnblogs.com/ch122633/p/8082746.html
Copyright © 2011-2022 走看看