Linux socket编程示例1

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

Linux socket编程示例  备忘一下,温故知新。
一、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示例

/*******************************
    client.c
********************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 8888

int main()
{
    /*1 创建socket*/
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd == -1)
    {
        perror("socket failed");
        exit(-1);
    }
    /*2 准备通信地址*/
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    /*设置为服务器进程的端口号*/
    addr.sin_port    = htons(PORT);
    /*服务器所在主机IP地址*/
    inet_aton("192.168.182.10", &addr.sin_addr);
    
    /*3 连接服务器*/
    int res = connect(sockfd, 
                      (struct sockaddr *)&addr,
                      sizeof(addr));
    if(res == -1)
    {
        perror("connect failed");
        exit(-1);
    }
    printf("连接服务器成功....\n");
    /*4 和服务器交换数据*/
    char buf[100] = {0};
    char *str = "借点钱可以吗...";
    write(sockfd, str, strlen(str))    ;
    read(sockfd, buf, sizeof(buf));
    printf("服务器说:%s\n", buf);

    /*关闭连接*/
    close(sockfd);
    return 0;
}
/************************************
    server.c
*************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 8888

int main()
{
    /*1 创建socket*/
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd == -1)
    {
        perror("socket failed");
        exit(-1);
    }
    /*2 准备通信地址*/
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port    = htons(PORT);
    inet_aton("192.168.182.10", &addr.sin_addr);
    
    /*3 绑定socket和通信地址*/
    int res = bind(sockfd,(struct sockaddr *)&addr,
                       sizeof(addr));
    if(res == -1)
    {
        perror("bind failed");
        exit(-1);
    }
    /*4 监听端口*/
    res = listen(sockfd, 100);
    if(res == -1)
    {
        perror("listen failed");
        exit(-1);
    }
    printf("开始监听%d端口,等待客户端连接...\n",
            PORT);
    /*5 处理接收客户端的连接请求*/
    //用于保存客户端地址信息
    struct sockaddr_in fromaddr;
    /*len 取0会是什么效果?*/
    socklen_t len = sizeof(fromaddr);
    int clientfd = accept(sockfd, 
                    (struct sockaddr *)&fromaddr,
                    &len);
    if(clientfd == -1)
    {
        perror("accept failed");
        exit(-1);
    }
    printf("有一个客户端连接到服务器,它是:%s\n",
            inet_ntoa(fromaddr.sin_addr));
    /*6 处理客户端数据*/
    char buf[100] = {0};
    int count = recv(clientfd, buf, sizeof(buf),0);
    printf("从客户端读取到%d字节:%s\n",
            count, buf);
    char *str = "欢迎你客户端";
    send(clientfd, str, strlen(str), 0);
    /*关闭连接*/
    close(clientfd);
    close(sockfd);
    return 0;
}

五、UDP示例

/********************************
    UDP_client.c
*********************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 12345
int main()
{
    /*1 创建socket*/    
    int sd = socket(PF_INET, SOCK_DGRAM, 0);
    if(sd == -1)
    {
        perror("socket failed");
        exit(-1);
    }
    /*2 准备地址*/
    struct sockaddr_in addr;
    addr.sin_family = PF_INET;
    addr.sin_port = htons(PORT);
    inet_aton("192.168.182.10",  &addr.sin_addr);
    /*3 进行通信*/
    char *str = "借点钱可以吗";
    sendto(sd, str, strlen(str), 0,
            (struct sockaddr *)&addr,
            sizeof(addr));
    char buf[100] = {0};
    int len = sizeof(addr);
    recvfrom(sd, buf, sizeof(buf), 0,
            (struct sockaddr *) &addr,
              &len);
    printf("服务器说:%s\n", buf);
    close(sd);
}
/********************************
    UDP_server.c
*********************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 12345
int main()
{
    /*1 创建socket*/    
    int sd = socket(PF_INET, SOCK_DGRAM, 0);
    if(sd == -1)
    {
        perror("socket failed");
        exit(-1);
    }
    /*2 准备地址*/
    struct sockaddr_in addr;
    addr.sin_family = PF_INET;
    addr.sin_port = htons(PORT);
    inet_aton("192.168.182.10",  &addr.sin_addr);
    /*3 socket addr 绑定*/
    int res = bind(sd, (struct sockaddr *)&addr,
                    sizeof(addr));
    if(res == -1)
    {
        perror("bind failed");
        exit(-1);
    }
    /*4 进行通信*/
    while(1)
    {
        char buf[100] = {0};
        struct sockaddr_in fromaddr;
        int len = sizeof(fromaddr);
        recvfrom(sd, buf, sizeof(buf), 0,
                 (struct sockaddr *) &fromaddr,
                 &len);
        printf("从客户端%s接收到数据:%s\n",
                inet_ntoa(fromaddr.sin_addr),
                buf);
        char *str = "没问题,借多少";
        sendto(sd, str, strlen(str), 0,
                (struct sockaddr *)&fromaddr,
                sizeof(fromaddr));
    }
    close(sd);

}

猜你喜欢

转载自blog.csdn.net/liuxizhen2009/article/details/83685617