zoukankan      html  css  js  c++  java
  • 基本的socket编程的介绍

    网络IPC:套接字

    用socket实现两个不同的主机之间的通信(涉及到一些基本的计算机网络知识  略过。。)

    服务器端:

    1.socket函数:生成一个套接字

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

    参数解析:domain:{AF_INET:Ipv4网络协议,AF_INET6:Ipv6网络协议}

        type:{tcp:SOCK_STREAM,udp:SOCK_DGRAM}

    protocol:指定socket所使用的传输协议编号,,一般为0;

    2.bind函数

    将套接字与地址关联

    int bind(int sockfd,const struct sockaddr *addr,socklen_t len);

    sockfd:套接字      *addr:地址结构的地址    len:地址结构的长度

    IPV4中,套接字地址用结构sockaddr_in表示:

    struct sockaddr_in {

    sa_family_t sin_family;  //通信域,一般为AF_INET

    in_port_t sin_port;       //接口地址,二进制

    struct in_addr sin_addr; //iP地址,二进制

    }

    3.listen函数:使服务器ip和这个端口处于监听状态,如果网络中某一客户机有连接请求,则接受请求。

    int listen(int sockfd,int backlog);

    sockfd:套接字   backlog:服务器能接受的最大请求,一般为10,最大为128

    4.accpet函数:接受客户端的请求,建立与客户机端的通信连接。当服务器处于监听状态时,客户端有连接请求,服务器不会马上处理,而是把这一个请求添加到等待队列中去,等到服务器空闲时再处理。处理时会生成一个新的套接字,这个套接字用于服务器和该客户端进行通信。原来的那个socket套接字继续用于监听。

    int accept(int s,struct sockaddr *addr,int *addrlen)

    s:socket返回值   addr:结构体指针变量,和bind是同种类型(系统会把远程客户机的IP和端口号放到这个指针变量中去)   addrlen:结构体长度

    成功的话返回的值是新的socket套接字

    5.recv函数:用新的套接字来接受远程客户端所传来的数据,并且将数据存储到参数buf中去

    原型:int recv(int sockfd,void *buf,int len,unsigned int flags);

    参数:sockfdà为前面accept的返回值.即new_fd,也就是新的套接字。

      bufà表示缓冲区

      lenà表示缓冲区的长度

      flagsà通常为0

    成功会返回接受数据的长度。

    6.send函数:用新的套接字发送数据给远程客户端

    原型:int send(int s,const void * msg,int len,unsigned int flags);

    参数:s为前面accept的返回值.即new_fd

      msg一般为常量字符串

      len表示长度

      flags通常为0

    客户端:

    1. connect函数:用来请求连接远程服务器,将参数sockfd 的socket 连至参数serv_addr 指定的服务器IP和端口号上去。

    原型:int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);

    参数:sockfd为前面socket的返回值,即sfd

      serv_addr为结构体指针变量,存储着远程服务器的IP与端口号信息。

      addrlen表示结构体变量的长度

    返回值:成功则返回0,失败返回-1

    2.close函数:当使用完文件后若已不再需要则可使用close()关闭该文件,并且close()会让数据写回磁盘,并释放该文件所占用的资源

    原型:int close(int fd);

    参数:fd为前面的sfd,new_fd

    返回值:若文件顺利关闭则返回0,发生错误时返回-1

    sample:一个简单的通信过程。ps:该程序没有用recv函数和send函数,而是用了read和write函数

    服务器端:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 #include<sys/types.h>
     5 #include<arpa/inet.h>
     6 #include<sys/socket.h>
     7 #include<netinet/in.h>
     8 int main(int argc,char *argv[])
     9 {
    10     int fd_listen;
    11     fd_listen=socket(AF_INET,SOCK_STREAM,0);//套接字
    12 
    13     if(fd_listen==-1)
    14     {
    15         perror("socket");
    16         exit(1);
    17     }
    18 struct sockaddr_in seraddr;  //地址结构体
    19  memset(&seraddr,0,sizeof(seraddr));
    20  seraddr.sin_family=AF_INET;  
    21  seraddr.sin_port=htons(1234);//端口
    22  seraddr.sin_addr.s_addr=inet_addr("192.168.1.182");//ip地址
    23  if(-1==bind(fd_listen,(const struct sockaddr*)&seraddr,(socklen_t)sizeof(seraddr)))
    24  {
    25    perror("bind");
    26    close(fd_listen);
    27    exit(1);
    28  }
    29  listen(fd_listen,10); //监听函数
    30 
    31  struct sockaddr_in peeraddr;
    32  memset(&peeraddr,0,sizeof(peeraddr));
    33  socklen_t len=sizeof(peeraddr);
    34  int fd_peer=accept(fd_listen,(struct sockaddr*)&peeraddr,&len);
    35 
    36  printf("who:%s:%d
    ",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port));
    37  if(fd_peer==-1)
    38  {
    39      perror("accept");
    40      close(fd_listen);
    41      exit(1);
    42  }
    43 char buf[1024]="";
    44 int readn=read(fd_peer,buf,1023);//从新套接字中读取数据
    45 printf("readn:%d,msg:%s
    ",readn,buf);
    46 char *p="-------------------";
    47 write(fd_peer,p,strlen(p));
    48 close(fd_listen);
    49 close(fd_peer);
    50 return 0;
    51 }
    View Code

    客户端:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 #include<sys/types.h>
     5 #include<sys/socket.h>
     6 #include<arpa/inet.h>
     7 #include<netinet/in.h>
     8 int main(int argc,char *argv[])
     9 {
    10     int sfd=socket(AF_INET,SOCK_STREAM,0);
    11     if(sfd==-1)
    12     {
    13         perror("socket");
    14         exit(1);
    15     }
    16     struct sockaddr_in peeraddr;
    17     peeraddr.sin_family=AF_INET;
    18     peeraddr.sin_port=htons(1234);
    19     peeraddr.sin_addr.s_addr=inet_addr("192.168.1.182");
    20 
    21     if(-1==connect(sfd,(struct sockaddr*)&peeraddr,sizeof(peeraddr)))//请求连接,把自己的信息添加到套接字中去
    22     {
    23         perror("connect");
    24         close(sfd);
    25     }
    26     char *p="hello world";
    27     write(sfd,p,strlen(p));
    28     char buf[1024]="";
    29     int readn=read(sfd,buf,1023);
    30     printf("readn:%d: %s
    ",readn,buf);
    31     close(sfd);
    32     return 0;
    33 }
    View Code

    总结:本程序模拟TCP协议实现了服务器端和客户机端的简单通信,介绍了整个过程。

  • 相关阅读:
    软件架构模式
    经济学基础
    使用vue-cli3新建一个项目,并写好基本配置
    vue+iview+less实现主题切换功能
    ivew table组件二次封装,解决slot-scope跨组件传递的问题
    vue-cli3使用less全局变量,不用每个组件引入less文件(亲测有效)
    vscode开发vue项目使用eslint+prettier格式化:保存时自动执行lint进行修复(升级篇,保存时可格式化模板和css)
    切换子路由时,父路由的组件会重新渲染
    更换路由时页面实现左右滑动的效果
    div设置为inline-block后,两个div之间有空隙
  • 原文地址:https://www.cnblogs.com/zhaoheng/p/4415691.html
Copyright © 2011-2022 走看看