• 套接口socket编程(Client/Server编程实例)


    基本概念                                                                                                                                         

    套接口也就是网络中的ID。网络通信,归根到底还是进程间通信(不同计算机上的进程间的通信)。在网络中,每一个节点(计算机或路由器)都有一个网络地址,也就是IP地址。

    • IP地址:在网络中唯一标识一台主机,32
    • 端口号:在主机中唯一标识一个进程,16
    • IP+port:在网络环境中唯一标识一个进程(socket)

          socket也称套接字,是linux文件的一种类型(伪文件:不占存储空间的文件。linux 有7中文件, 1.普通文件  2.目录(d)3.字符设备文件(c) 4.块设备文件(b) 5.套接口文件(s)[如我们开启MySQL服务后,在/var/lib/mysql/下生成的mysql.sock文件,关闭MySQL服务后,这个文件就消失了],6.管道(p):有两端,读端 r:流出 fd[0]     写段w:流入 fd[1]         7.符号链接文件(l)[有点儿像WIN下的快捷方式]  其中占存储的有三种:普通,目录,软链接)

           socket成对出现,

           一个文件描述符指向两个缓冲区,一个读一个写。

    预备知识                                                                                                                                          、

    网路字节序:

           TCP/IP规定,网路数据流应采用大端字节序,即低地址高字节。(大端:低地址--高位   高地址--地位    小端:低--低 高--高,即端口号和IP地址都是以网路字节序存储的,网络字节序使用的是大端模式。称给某个系统所采用的字节序为主机字节序,它可能是小端模式也可能是大端模式。

           为使网络编程具有可移植性,使同样的C代码在大端和小端计算机上编译后能正常运行,可以调用一下库函数做网络字节序和主机字节序的转换。

    #include<arpa/inet.h>
    uint32_t  htoal(uint32_t hostlong);
    uint16_t  htons(uint16_t hostshort);
    //返回的是网络字节序
    uint32_t ntoh1(uint32_t netlong);
    uint16_t ntohs(uint16_t netshort);
    //返回的主机字节序
    //h表示host,to,n代表network,s代表short,l表示long
    //端口16位 ,ip 32位

     套接口的数据结构                                                                                                                                

          在Linux中,每一种协议都有自己的网络地址数据结构,以sockaddr_开头,如IPV4对应的是sockaddr_in.

               //man 7 ip 查看
    
               struct sockaddr_in {
                   sa_family_t    sin_family; /* address family: AF_INET */
                /*套接口结构地址族,如IPV4为AF_INET*/
                   in_port_t      sin_port;   /* port in network byte order */
                /*16位TCP或UDP端口号,网络字节顺序*/
                   struct in_addr sin_addr;   /* internet address */
               };
    
               /* Internet address. */
               struct in_addr {
                   uint32_t       s_addr;     /* address in network byte order */
               };

    C/S编程                                                                                                                                                  

    服务器是指在网络上提供服务的应用程序,客户机是指用户为了得到某种服务所需要 运行的应用程序,即申请服务的程序。一个服务器程序可以同时接收多个客户机的请求。

     

    server.c:
    socket() 建立套接字
    bind()  绑定IP 端口号(struct sockaddr_in addr 初始化)
    listen() 指定最大同时发起连接数
    accept()  阻塞等待客户端发起连接
    read()
    小--大
    write 给客户端
    close();
    client.c:
    socket();
    bind();可以依赖“隐式绑定”,即写不写都行
    connect();发起连接
    write();
    read();
    close();
     1 #include<stdio.h>
     2 #include<unistd.h>
     3 #include<sys/socket.h>
     4 #include<stdlib.h>
     5 #include<arpa/inet.h>
     6 #include<ctype.h>
     7 #include<strings.h>
     8 #define SERV_PORT 6666 //端口号
     9 int main(void)
    10 {
    11    int lfd,cfd;//定义套接口描述符
    12    struct sockaddr_in serv_addr;//定义服务器IPV4套接口地址数据结构serv_addr
    13    struct sockaddr_in clie_addr;//d定义客户端client
    14    socklen_t clie_addr_len;
    15    char buf[BUFSIZ],clie_IP[BUFSIZ];//用BUFSIZ就不需要自己定义宏了
    16    int i,n;
    17    lfd=socket(AF_INET,SOCK_STREAM,0);//AF_INET:IPV4 AF_INET6:IPV6
    18    bzero(&serv_addr,sizeof(serv_addr));//清0,memset清任何数 
    19    serv_addr.sin_family=AF_INET;//设置addr的成员信息
    20    serv_addr.sin_port=htons(SERV_PORT);//本地字节序转换为网络字节序
    21    serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);//IP地址设为本地IP INADDR_ANY本地任意IP
    22 
    23    bind(lfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));//绑定端口
    24 
    25    listen(lfd,128);//最多可以接受128个客户端的请求,监听ifd描述符
    26 
    27    clie_addr_len=sizeof(clie_addr);
    28    cfd=accept(lfd,(struct sockaddr *)&clie_addr,&clie_addr_len);//bind accept connect 需要强转
    29    printf("client IP:%s,client port:%d
    ",inet_ntop(AF_INET,&clie_addr.sin_addr,clie_IP,sizeof(clie_IP)),ntohs(clie_addr.sin_port));
    30    while(1){
    31    n= read(cfd,buf,sizeof(buf));
    32    for(i=0;i<n;i++)
    33    {
    34      buf[i]=toupper(buf[i]);//下写转换为大写
    35    }
    36    write(cfd,buf,n);
    37    }
    38    close(lfd);
    39    close(cfd);
    40 
    41    return 0;
    42 
    43 }
    server.c
     1 #include<stdio.h>
     2 #include<unistd.h>
     3 #include<sys/socket.h>
     4 #include<stdlib.h>
     5 #include<arpa/inet.h>
     6 #include<ctype.h>
     7 #include<string.h>
     8 #define SERV_PORT 6666
     9 #define SERV_IP "127.0.0.1 "
    10 int main(void)
    11 {
    12     int cfd;
    13     int n;
    14     char buf[BUFSIZ];
    15     struct sockaddr_in serv_addr;
    16    // socklen_t serv_addr_len;
    17     cfd = socket(AF_INET,SOCK_STREAM,0);
    18     memset(&serv_addr,0,sizeof(serv_addr));
    19     serv_addr.sin_family=AF_INET;//设置addr的成员信息
    20     serv_addr.sin_port=htons(SERV_PORT);//本地字节序转换为网络字节序
    21     inet_pton(AF_INET,SERV_IP,&serv_addr.sin_addr.s_addr);
    22  //    serv_addr.sin_addr=*((struct in_addr *)host->haddr);
    23     connect(cfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));//客户端程序发起连接请求
    24    while(1)
    25    {
    26    fgets(buf,sizeof(buf),stdin);//hello world ----fgets---"hello world
    "从键盘写 
    27    write(cfd,buf,strlen(buf));
    28    n=read(cfd,buf,sizeof(buf));
    29    write(STDOUT_FILENO,buf,n);
    30    }
    31    close(cfd);
    32    return 0;
    33 }
    client.c

  • 相关阅读:
    Python学习笔记:pd.drop删除行或列
    Python学习笔记:pd.droplevel删除指定级别索引、列名
    Python学习笔记:pd.date_range构造时间序列
    yum安装时提示app is currently holding the yum lock; waiting for it to exit
    Mysql模糊查询like效率,以及更高效的写法
    解决css文件返回格式Content-Type为text/html问题
    4 20210412-1 原型设计作业
    第八周课程总结
    第六周&java实验报告四
    第四周总结
  • 原文地址:https://www.cnblogs.com/wy9264/p/10478353.html
Copyright © 2020-2023  润新知