zoukankan      html  css  js  c++  java
  • Linux socket编程示例(最简单的TCP和UDP两个例子)

    一、socket编程

       网络功能是Uinux/Linux的一个重要特点,有着悠久的历史,因此有一个非常固定的编程套路。

      基于TCP的网络编程:

        基于连接, 在交互过程中, 服务器和客户端要保持连接, 不能断开。重发一切出错数据、数据验证, 保证数据的正确性、完整性和顺序性,

        缺点是消耗的资源比较大。

      基于UDP的网络编程:

        无连接协议, 在网络交互过程中不保持连接, 只需要在发送数据时连接一下, 不重发、验证数据。优点是资源消耗少, 数据的可靠性完整性

        顺序性得不到保证。

    二、编程步骤:

        服务器:

          ① 创建socket(套接字) socket()

          ② 准备通信地址

          ③ 将创建的socket和通信地址绑定 bind()

          ④ 监听端口 listen()

          ⑤ 等待客户端连接 accpet()

          ⑥ 通信双方收发数据 read()/write()

                     send()/recv()

          ⑦ 关闭socket

        客户端:

          ① 创建socket(套接字) socket()

          ② 准备通信地址

          ③ 连接服务器 connect()

          ④ 收发数据 read()/write()

                 send()/recv()

          ⑤ 关闭socket  

    三、API详解

      ① socket()函数

        int socket(domain, type, protocol)

        domain:

            AF_UNIX/AF_LOCAL/AF_FILE: 本地通信

            AF_INET: 网络通信 ipv4

            AF_INET6: 网络通信 ipv6

            注:如果AF换成PF效果一样

        type, 选择通信类型, 主要包括:

            SOCK_STREAM: TCP

            SOCK_DGRAM : UDP

        protocol, 本来应该指定通信协议, 但现在基本废弃, 因为协议已经在前面两个参数指定完成,给0即可

      ② bind()函数

        int bind(int sockfd, struct sockaddr *addr, size)

        sockfd: 要绑定的套接字描述符

        size: 第二个参数占据的内存空间大小

        addr: 涉及三个数据结构struct sockaddr, sockaddr_un, sockaddr_in

          sockaddr, 主要用于函数参数, 不负责存储数据

          sockaddr_un, 当着本地通信时, 用于本地通信使用的地址 (sys/un.h)

          sockaddr_in, 当着网络通信时, 负责存储网络通信的地址数据

          struct sockaddr_in {

              sin_family; //用于指定协议族, 和socket()的参数保持一致

              sin_port; //网络通信使用的端口号

              sin_addr; //存储网络通信的ip地址 

          }          

      ③ htons

      ④ inet_aton         

      ⑤ listen()函数

        int listen(int sockfd, int backlog)

         sockfd: 将sockfd参数所标识的套接字为被动模式, 使之可以接受连接请求

         backlog: 表示未决连接请求队列的最大长度, 即允许最多有多少个未决连接请求存在。若服务器的未决连接请求已达到该值, 则客户端通过 connect()连接服务器的操作将返回-1,且error为ECONNREFUSED

      ⑥ accpet()函数

        int accpet(sockfd, struct sockaddr* addr, socklen_t *addrlen)

         从sockfd参数所标识套接字对应未决连接请求队列中取出的一个连接请求, 同时创建一个新的套接字,用于该连接通信, 返回套接字的描述符

         addr和addrlen 用于输出连接请求发起者的地址信息

         返回值: 为新创建用于和客户端通信的套接字描述符 失败-1, error  

      ⑦ inet_ntoa

      ⑧ recv()函数  

       int recv(int sockfd, buf, len, flags)

         flags, 通常取0: 阻塞收取数据

            O_NONBLOCK: 不阻塞, 如果未收到数据, 返回错误信息

         返回值:

            >0, 实际接受数据字节数

            -1 , 出错, error

             0 , 通信的另一端关闭

      ⑨ send()函数

       int send(int sockfd, buf, len, flags)

         flags: 通常取0, 阻塞发送

         O_NONBLOCK: 不阻塞, 如果未收到数据, 返回错误信息

      ⑩ connect()函数

       int connect(int sockfd, addr, addr_len)

         参数参考bind()      

    四、TCP示例


    复制代码
    1 /*******************************
    2 client.c
    3 ********************************/
    4 #include <stdio.h>
    5 #include <stdlib.h>
    6 #include <string.h>
    7 #include <unistd.h>
    8 #include <sys/types.h>
    9 #include <sys/socket.h>
    10 #include <netinet/in.h>
    11 #include <arpa/inet.h>
    12 #define PORT 8888
    13
    14 int main()
    15 {
    16 /*1 创建socket*/
    17 int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    18 if(sockfd == -1)
    19 {
    20 perror("socket failed");
    21 exit(-1);
    22 }
    23 /*2 准备通信地址*/
    24 struct sockaddr_in addr;
    25 addr.sin_family = AF_INET;
    26 /*设置为服务器进程的端口号*/
    27 addr.sin_port = htons(PORT);
    28 /*服务器所在主机IP地址*/
    29 inet_aton("192.168.182.10", &addr.sin_addr);
    30
    31 /*3 连接服务器*/
    32 int res = connect(sockfd,
    33 (struct sockaddr *)&addr,
    34 sizeof(addr));
    35 if(res == -1)
    36 {
    37 perror("connect failed");
    38 exit(-1);
    39 }
    40 printf("连接服务器成功.... ");
    41 /*4 和服务器交换数据*/
    42 char buf[100] = {0};
    43 char *str = "借点钱可以吗...";
    44 write(sockfd, str, strlen(str)) ;
    45 read(sockfd, buf, sizeof(buf));
    46 printf("服务器说:%s ", buf);
    47
    48 /*关闭连接*/
    49 close(sockfd);
    50 return 0;
    51 }
    复制代码

    复制代码
    1 /************************************
    2 server.c
    3 *************************************/
    4
    5 #include <stdio.h>
    6 #include <stdlib.h>
    7 #include <string.h>
    8 #include <unistd.h>
    9 #include <sys/types.h>
    10 #include <sys/socket.h>
    11 #include <netinet/in.h>
    12 #include <arpa/inet.h>
    13 #define PORT 8888
    14
    15 int main()
    16 {
    17 /*1 创建socket*/
    18 int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    19 if(sockfd == -1)
    20 {
    21 perror("socket failed");
    22 exit(-1);
    23 }
    24 /*2 准备通信地址*/
    25 struct sockaddr_in addr;
    26 addr.sin_family = AF_INET;
    27 addr.sin_port = htons(PORT);
    28 inet_aton("192.168.182.10", &addr.sin_addr);
    29
    30 /*3 绑定socket和通信地址*/
    31 int res = bind(sockfd,(struct sockaddr *)&addr,
    32 sizeof(addr));
    33 if(res == -1)
    34 {
    35 perror("bind failed");
    36 exit(-1);
    37 }
    38 /*4 监听端口*/
    39 res = listen(sockfd, 100);
    40 if(res == -1)
    41 {
    42 perror("listen failed");
    43 exit(-1);
    44 }
    45 printf("开始监听%d端口,等待客户端连接... ",
    46 PORT);
    47 /*5 处理接收客户端的连接请求*/
    48 //用于保存客户端地址信息
    49 struct sockaddr_in fromaddr;
    50 /*len 取0会是什么效果?*/
    51 socklen_t len = sizeof(fromaddr);
    52 int clientfd = accept(sockfd,
    53 (struct sockaddr *)&fromaddr,
    54 &len);
    55 if(clientfd == -1)
    56 {
    57 perror("accept failed");
    58 exit(-1);
    59 }
    60 printf("有一个客户端连接到服务器,它是:%s ",
    61 inet_ntoa(fromaddr.sin_addr));
    62 /*6 处理客户端数据*/
    63 char buf[100] = {0};
    64 int count = recv(clientfd, buf, sizeof(buf),0);
    65 printf("从客户端读取到%d字节:%s ",
    66 count, buf);
    67 char *str = "欢迎你客户端";
    68 send(clientfd, str, strlen(str), 0);
    69 /*关闭连接*/
    70 close(clientfd);
    71 close(sockfd);
    72 return 0;
    73 }
    复制代码
    五、UDP示例


    复制代码
    1 /********************************
    2 UDP_client.c
    3 *********************************/
    4 #include <stdio.h>
    5 #include <stdlib.h>
    6 #include <string.h>
    7 #include <unistd.h>
    8 #include <sys/types.h>
    9 #include <sys/socket.h>
    10 #include <netinet/in.h>
    11 #include <arpa/inet.h>
    12
    13 #define PORT 12345
    14 int main()
    15 {
    16 /*1 创建socket*/
    17 int sd = socket(PF_INET, SOCK_DGRAM, 0);
    18 if(sd == -1)
    19 {
    20 perror("socket failed");
    21 exit(-1);
    22 }
    23 /*2 准备地址*/
    24 struct sockaddr_in addr;
    25 addr.sin_family = PF_INET;
    26 addr.sin_port = htons(PORT);
    27 inet_aton("192.168.182.10", &addr.sin_addr);
    28 /*3 进行通信*/
    29 char *str = "借点钱可以吗";
    30 sendto(sd, str, strlen(str), 0,
    31 (struct sockaddr *)&addr,
    32 sizeof(addr));
    33 char buf[100] = {0};
    34 int len = sizeof(addr);
    35 recvfrom(sd, buf, sizeof(buf), 0,
    36 (struct sockaddr *) &addr,
    37 &len);
    38 printf("服务器说:%s ", buf);
    39 close(sd);
    40 }
    复制代码

    复制代码
    1 /********************************
    2 UDP_server.c
    3 *********************************/
    4 #include <stdio.h>
    5 #include <stdlib.h>
    6 #include <string.h>
    7 #include <unistd.h>
    8 #include <sys/types.h>
    9 #include <sys/socket.h>
    10 #include <netinet/in.h>
    11 #include <arpa/inet.h>
    12
    13 #define PORT 12345
    14 int main()
    15 {
    16 /*1 创建socket*/
    17 int sd = socket(PF_INET, SOCK_DGRAM, 0);
    18 if(sd == -1)
    19 {
    20 perror("socket failed");
    21 exit(-1);
    22 }
    23 /*2 准备地址*/
    24 struct sockaddr_in addr;
    25 addr.sin_family = PF_INET;
    26 addr.sin_port = htons(PORT);
    27 inet_aton("192.168.182.10", &addr.sin_addr);
    28 /*3 socket addr 绑定*/
    29 int res = bind(sd, (struct sockaddr *)&addr,
    30 sizeof(addr));
    31 if(res == -1)
    32 {
    33 perror("bind failed");
    34 exit(-1);
    35 }
    36 /*4 进行通信*/
    37 while(1)
    38 {
    39 char buf[100] = {0};
    40 struct sockaddr_in fromaddr;
    41 int len = sizeof(fromaddr);
    42 recvfrom(sd, buf, sizeof(buf), 0,
    43 (struct sockaddr *) &fromaddr,
    44 &len);
    45 printf("从客户端%s接收到数据:%s ",
    46 inet_ntoa(fromaddr.sin_addr),
    47 buf);
    48 char *str = "没问题,借多少";
    49 sendto(sd, str, strlen(str), 0,
    50 (struct sockaddr *)&fromaddr,
    51 sizeof(fromaddr));
    52 }
    53 close(sd);
    54
    55 }

    http://www.cnblogs.com/jiangson/p/5977601.html

  • 相关阅读:
    HDU 1573: X问题
    HDU 1370: Biorhythms
    Break Number --AtCoder
    Cat Snuke and a Voyage --AtCoder
    Fennec VS. Snuke --AtCoder
    Splitting Pile --AtCoder
    Sharing Cookies --AtCoder
    GLB串
    派(Dispatch)
    你知道那棵杨树底下有什么吗
  • 原文地址:https://www.cnblogs.com/findumars/p/8030439.html
Copyright © 2011-2022 走看看