zoukankan      html  css  js  c++  java
  • socket(二)

    TCP客户/服务器模型

    1.客户端调用序列

    客户端编程序列如下:

    1. 调用socket函数创建套接字
    2. 调用connect连接服务器端
    3. 调用I/O函数(read/write)与服务器端通讯
    4. 调用close关闭套接字

    2.服务器端调用序列

    服务端的编程序列如下:

    1. 调用socket函数创建套接字
    2. 调用bind绑定本地地址和端口
    3. 调用listen启动监听
    4. 调用accept从已连接队列中提取客户端连接
    5. 调用I/O函数(read/write)与客户端通讯
    6. 调用close函数关闭套接字

    回射客户/服务器

    socket函数

      包含头文件 <sys/socket.h>

      功能:创建一个套接字用于通信(socket - create an endpoint for communication)

      原型

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

      参数

        domain:指定通信协议族(protocol family)

        type:指定socket类型,流式套接字SOCK_STREAM,数据报套接字SOCK_DGRAM,原始套接字SOCK_RAW

        protocol:协议类型

      返回值:成功返回非负整数,它与文件描述符类似,我们把它称为套接字描述字,简称套接字。失败返回 -1

    拓展:

      域参数指定一个通信域;这将选择用于通信的协议族。这些族在<sys/socket.h>中定义。(The domain argument specifies a communication domain; this selects the protocol family which will be used for communication. These families are defined in <sys/socket.h>.)

    domain:

        目前了解的格式包括:(The currently understood formats include:)   

        Name         Purpose               Man page
        AF_UNIX,       AF_LOCAL Local communication      unix(7)
        AF_INET        IPv4 Internet protocols          ip(7)
        AF_INET6      IPv6 Internet protocols          ipv6(7)
        AF_IPX          IPX - Novell protocols
        AF_NETLINK      Kernel user interface device       netlink(7)
        AF_X25         ITU-T X.25 / ISO-8208 protocol        x25(7)
        AF_AX25       Amateur radio AX.25 protocol
        AF_ATMPVC      Access to raw ATM PVCs
        AF_APPLETALK     Appletalk                ddp(7)
        AF_PACKET      Low level packet interface          packet(7)

    type:

      套接字具有指定的类型,该类型指定通信语义。目前定义的类型有:(The socket has the indicated type, which specifies the communication semantics.  Currently defined types are:)

      SOCK_STREAM     提供有序、可靠、双向、基于连接的字节流。可能支持带外数据传输机制。(Provides sequenced, reliable, two-way, connection-based byte streams. An out-of-band data transmission mechanism may be supported.)

      SOCK_DGRAM      支持数据报(无连接,不可靠的固定最大长度的消息)。(Supports datagrams (connectionless, unreliable messages of a fixed maximum length).)

      SOCK_SEQPACKET   为最大长度固定的数据报提供有序、可靠、基于双向连接的数据传输路径;消费者需要在每次输入系统调用时读取整个数据包。(Provides a sequenced, reliable, two-way connection-based data transmission path for datagrams of fixed               maximum length; a consumer is required to read anentire packet with each input system call.)

      SOCK_RAW       提供原始网络协议访问。(Provides raw network protocol access.)

      SOCK_RDM       提供不保证排序的可靠数据报层。(Provides a reliable datagram layer that does not guarantee ordering.)

      SOCK_PACKET      过时的,不应用于新项目;参考手册(7)。( Obsolete and should not be used in new programs; see packet(7).)

    某些套接字类型可能不能由所有协议族实现;例如,SOCK_SEQPACKET没有在AF_INET中实现。(Some socket types may not be implemented by all protocol families; for example, SOCK_SEQPACKET is not implemented for AF_INET.)

    由于Linux 2.6.27,类型参数有第二个用途:除了指定套接字类型外,它还可以包括按位或下列任何一个值,以修改socket()的行为:

    (Since Linux 2.6.27, the type argument serves a second purpose: in addition to specifying a socket type, it may include the bitwise OR of any of the following values, to modify the behavior of socket():)

      SOCK_NONBLOCK    在新打开的文件描述中设置O_NONBLOCK文件状态标志。使用这个标志可以节省对fcntl(2)的额外调用,从而获得相同的结果。( Set the O_NONBLOCK file status flag on the new open file description. Using this flag saves extra calls to               fcntl(2) to achieve the same result.)

      SOCK_CLOEXEC       在新的文件描述符上设置close-on-exec (FD_CLOEXEC)标志。查看open(2)中关于O_CLOEXEC标志的说明,了解为什么可能使用它的原因‐。( Set the close-on-exec (FD_CLOEXEC) flag on the new file descriptor. See the description               of the O_CLOEXEC flag in open(2) for reasons why this may be use‐ful.)

    bind函数

     1 #include <sys/types.h> /* See NOTES */
     2 #include <sys/socket.h>
     3 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
     5   @param sockfd : 套接字描述符
     6   @param addr : 通用套接字地址结构的地址
     7   @param addrlen : 套接字地址结构的长度
     8 
     9   @return
    10   成功返回 0
    11   失败返回 -1

      bind() 函数用于绑定一个固定的 ip 地址与端口号,为客户端提供可以访问的地址,相应的ip 地址与端口号在通用地址结构中存储.

      struct sockaddr 结构体为通用地址结构,主要用于存储 ip 地址与端口号

    1  struct sockaddr {
    2  sa_family_t sa_family;
    3  char sa_data[14];
    4  };
    5  @sa_family : 地址族 AF_INET
    6  @sa_data : ip地址与端口号
    • 由于通用地址结构 ip 地址与端口号保存在一个数组中,不便于区分,在 Internet 协议族重新设计了地址结构,这个地址结构为 struct sockaddr_in
    • ip 地址 与端口号使用单独的成员来表示
    • 同时为了兼容 bind() 函数接口,使用了数组进行填充,保持和原结构一致
    1 struct sockaddr_in {
    2     __kernel_sa_family_t sin_family; /* 地址族*/
    3     __be16 sin_port; /* 端口号 */
    4     struct in_addr sin_addr; /* ip 地址*/
    5     /* 填充数组,保持与 struct sockaddr 结构大小一致 */
    6     unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - sizeof(unsigned short int) - sizeof(struct in_addr)];
    7 };

    listen、

      流 socket 通常可以分为主动和被动两种:在默认情况下,使用 socket() 创建的 socket 是主动的,一个主动的 socket 可用在connect() 调用中来建立一个到一个被动 socket 的连接.一个被动 socket 是一个通过调用 listen() 以被标记成允许接入连接的 socket.在大多数使用流 socket 的应用场景,服务器会执行被动式打开,而客户端会执行主动式

      listen() 函数的原型如下:

    1 #include <sys/types.h> /* See NOTES */
    2 #include <sys/socket.h>
    3 int listen(int sockfd, int backlog);
    4 @param sockfd : socket 文件描述符
    5 @param backlog : 未决连接的数量

    accept、

      accept() 系统调用在文件描述符 sockfd 引用的监听流 socket 上接受一个接入连接,如果在调用 accept() 时不存在未决的连接,那么调用就会阻塞直到有连接请求到达为止

      accpet() 函数的原型为:

    1 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    2 @param sockfd : 套接字文件描述符
    3 @param addr : 客户端地址结构对象指针
    4 @param addrlen :地址结构长度指针
    5 
    6 @return
    7 成功 : 返回新的文件描述符

    connect、

      connect() 函数将文件描述符 sockfd 引用的主动 socket 连接到地址通过 addr 和 addrlen 指定的监听 socket 上

    1 int connect(int sockfd, const struct sockaddr *addr,
    2 socklen_t addrlen);
    3 @param sockfd : 文件描述符
    4 @param addr : 服务器地址结构对象的指针
    5 @param addrlen :地址结构的长度
    6 
    7 @return :
    8 成功 : 返回 0
    9 失败 : 返回 -1

    server.c

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #include <error.h>
     5 
     6 #include <sys/socket.h>
     7 #include <sys/types.h>
     8 #include <arpa/inet.h>
     9 //#include <sys/un.h>
    10 
    11 #define handle_error(message) 
    12     do 
    13     { 
    14         perror(message); 
    15         exit(EXIT_FAILURE); 
    16     } while(0);
    17 
    18 int getSocketFd()
    19 {
    20     int socket_listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    21     if (socket_listenfd < 0)
    22         handle_error("socket");
    23    
    24     return socket_listenfd;
    25 }
    26 
    27 void bindSocketFd(int socket_listenfd)
    28 {
    29     struct sockaddr_in serverAddr;
    30     memset(&serverAddr, 0, sizeof(serverAddr));
    31     serverAddr.sin_family = PF_INET;
    32     serverAddr.sin_port = htons(7777);
    33     serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    34     /*serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");*/
    35     /*inet_ntoa("127.0.0.1", &serverAddr.sin_addr);*/
    36 
    37     if (bind(socket_listenfd, (struct sockaddr * )&serverAddr, sizeof(serverAddr)) < 0)
    38         handle_error("bind");
    39 
    40     if(listen(socket_listenfd, SOMAXCONN) < 0)
    41         handle_error("listen");
    42 
    43     struct sockaddr_in clientAddr;
    44     memset(&clientAddr, 0, sizeof(clientAddr));
    45     int lengthOfClientAddr = sizeof(clientAddr);
    46     int connectFd = 0;
    47     if((connectFd = accept(socket_listenfd, (struct sockaddr * )&clientAddr, &lengthOfClientAddr)) < 0)
    48         handle_error("acept");
    49 
    50     char recvBuf[1024];
    51     while (1)
    52     {
    53         memset(recvBuf, 0, sizeof(recvBuf));
    54         int ret = read(connectFd, recvBuf, sizeof(recvBuf));
    55 
    56         fputs(recvBuf, stdout);
    57         write(connectFd, recvBuf, ret);
    58     }
    59 
    60     close(socket_listenfd);
    61 
    62 }
    63 
    64 int main(int argv, char * argc[])
    65 {
    66     int socket_listenfd = getSocketFd();
    67 
    68     bindSocketFd(socket_listenfd);
    69 
    70     return 0;
    71 }

    client.c

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #include <unistd.h>
     5 #include <error.h>
     6 
     7 #include <sys/types.h>
     8 #include <sys/socket.h>
     9 #include <arpa/inet.h>
    10 #include <netinet/in.h>
    11 
    12 #define handle_error(message) 
    13     do 
    14     { 
    15         perror(message); 
    16         exit(EXIT_FAILURE); 
    17     } while(0);
    18 
    19 void clientToServer()
    20 {
    21     int clientSockFd;
    22     if((clientSockFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
    23         handle_error("client socket");
    24     
    25     struct sockaddr_in clientAddr;
    26     memset(&clientAddr, 0, sizeof(clientAddr));
    27     clientAddr.sin_family = PF_INET;
    28     clientAddr.sin_port = htons(7777);
    29     clientAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    30 
    31     if(connect(clientSockFd, (struct sockaddr * )&clientAddr, sizeof(clientAddr)) < 0)
    32         handle_error("client connect");
    33 
    34     char sendBuf[1024] = {0};
    35     char recvBuf[1024] = {0};
    36 
    37     while (fgets(sendBuf, sizeof(sendBuf), stdin) != NULL)
    38     {
    39         write(clientSockFd, sendBuf, sizeof(sendBuf));
    40         read(clientSockFd, recvBuf, sizeof(recvBuf));
    41         
    42         fputs(recvBuf, stdout);
    43         memset(sendBuf, 0, sizeof(sendBuf));
    44         memset(recvBuf, 0, sizeof(recvBuf));
    45     }
    46 
    47     close(clientSockFd);
    48 }
    49 
    50 int main(int argv, char * argc[])
    51 {
    52     clientToServer();
    53 
    54     return 0;
    55 }
  • 相关阅读:
    android xml属性大全
    Activity 中传递数据
    android 界面布局 很好的一篇总结
    Android基础类之BaseAdapter
    自定义android的tab样式
    android之Uri的常用几个例子
    我的第一篇博客
    [解题报告]272 TEX Quotes
    [解题报告]10071 Back to High School Physics
    [解题报告]113 Power of Cryptography
  • 原文地址:https://www.cnblogs.com/Reverse-xiaoyu/p/12820482.html
Copyright © 2011-2022 走看看