当前位置:网站首页>Socket socket programming

Socket socket programming

2022-07-07 11:08:00 Exy-

Catalog

common socket API

sockaddr structure

encapsulation UDPSocket

udp Client code

udp Server code

encapsulation TCPSocket

tcp Server side

 tcp client


common socket API

//  establish  socket  File descriptor  (TCP/UDP,  client  +  The server )
int socket(int domain, int type, int protocol);
//  Binding port number  (TCP/UDP,  The server )      
int bind(int socket, const struct sockaddr *address,socklen_t address_len);
//  Start listening socket (TCP,  The server )
int listen(int socket, int backlog);
//  Receiving request  (TCP,  The server )
int accept(int socket, struct sockaddr* address,socklen_t* address_len);
//  Establishing a connection  (TCP,  client )
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

sockaddr structure

socket API It is an abstract network programming interface , It is suitable for various underlying network protocols , Such as IPv4IPv6. However , Different network protocols have different address formats
  • IPv4 and IPv6 The address format of is defined in netinet/in.h in ,IPv4 Address use sockaddr_in The structure represents , Include 16 Bit address type , 16 Bit port number and 32 position IP Address .
  • IPv4IPv6 Address types are defined as constants AF_INETAF_INET6. such , Just get something sockaddr The first address of the structure , You don't need to know what kind of sockaddr Structure , You can determine the content of the structure according to the address type field .
  • socket API You can use it all struct sockaddr * Type said , It needs to be converted into sockaddr_in; That's good This is the universality of the program , You can receive IPv4, IPv6, as well as UNIX Domain Socket All kinds of sockaddr Structure pointer as a parameter ;
although socket api The interface of is sockaddr, But we're really based on IPv4 When programming , The data structure used is sockaddr_in; In this structure, the main There should be three parts of information : Address type , Port number , IP Address .

encapsulation UDPSocket

//udpsocket.cpp
#include<cstdio>
#include<unistd.h>
#include<iostream>
#include<string.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<sys/socket.h>
using namespace std;
class UdpSocket
{

  public:
    UdpSocket()
      :_sockfd(-1)
    {}
    bool Socket(){
      _sockfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
      if(_sockfd<0)
      {
        perror("socket error");
        return false;
      }
      return true;
    }
    bool Bind(const std::string &ip,int port)
    {
      struct sockaddr_in addr;
      addr.sin_family=AF_INET;
      addr.sin_port=htons(port);
      addr.sin_addr.s_addr=inet_addr(ip.c_str());
      socklen_t len=sizeof(struct sockaddr_in);
      if(bind(_sockfd,(struct sockaddr*)&addr,len)<0)
      {
        perror("bind error");
        return false;
      }
      return true;
    }
    bool Send(const std::string &data,const std::string &ip,int port)
    {
      struct sockaddr_in peeraddr;
      peeraddr.sin_family=AF_INET;
      peeraddr.sin_port=htons(port);
      peeraddr.sin_addr.s_addr=inet_addr(ip.c_str());
      socklen_t len=sizeof(struct sockaddr_in);
      int ret=sendto(_sockfd,&data[0],data.size(),0,(struct sockaddr*)&peeraddr,len);
      if(ret<0)
      {
        perror("sendto error");
        return false;
      }
      return true;
    }
    bool Recv(std::string *buf,std::string *ip=NULL,int *port=NULL)
    {
      struct sockaddr_in peeraddr;
      socklen_t len=sizeof(struct sockaddr_in);
      char tmp[4096]={0};
      int ret=recvfrom(_sockfd,tmp,4095,0,(struct sockaddr*)&peeraddr,&len);
      if(ret<0)
      {
        perror("recvfrom error");
        return false;
      }
      buf->assign(tmp,ret);
      if(ip!=NULL)
        *ip=inet_ntoa(peeraddr.sin_addr);
      if(port!=NULL)
        *port=ntohs(peeraddr.sin_port);
      return true;
    }
    bool Close()
    {
      if(_sockfd>0)
      {
        close(_sockfd);
        _sockfd=-1;
      }
      return true;
    }

  private:
    int _sockfd;
};

udp Client code

#include<iostream>
#include<cstdlib>
#include"udpsocket.cpp"
#include<string.h>
#define CHECK_RET(q) if((q)==false){return -1;}
using namespace std;
int main(int argc,char*argv[])
{
  if(argc<3)
  {
    cout<<"usage: Please enter the server address information !\n";
    cout<<"\t./udp_client 192.168.1.2 9000\n";
    return -1;
  }
  string srv_ip=argv[1];
  int srv_port=atoi(argv[2]);
  UdpSocket sock;
  CHECK_RET(sock.Socket());
  while(1)
  {
    string buf;
    cout<<"client input";
    cin>>buf;
    CHECK_RET(sock.Send(buf,srv_ip,srv_port));
    buf.clear();
    CHECK_RET(sock.Recv(&buf));
    cout<<"sever response: "<<buf<<endl;
  }
  sock.Close();
  return 0;
  
}

udp Server code

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<string.h>
int main(int argc,char*argv[])
{
  if(argc<3)
  {
    printf("usage: ./udp_srv 192.168.1.2 9000\n");
    return -1;
  }
  char* srv_ip=argv[1];
  int srv_port=atoi(argv[2]);
  int sockfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
  if(sockfd<0)
  {
    perror("socket error");
    return -1;
  }
  struct sockaddr_in addr;
  addr.sin_family=AF_INET;
  addr.sin_port=htons(srv_port);
  addr.sin_addr.s_addr=inet_addr(srv_ip);
  socklen_t len=sizeof(addr);
  int ret=bind(sockfd,(struct sockaddr*)&addr,len);
  if(ret<0)
  {
    close(sockfd);
    perror("bind error");
    return -1;
  }
  //3. receive data , Receive the peer address 
  while(1){
    char buf[4096]={0};
    struct sockaddr_in client_addr;
    len=sizeof(client_addr);
    ret=recvfrom(sockfd,buf,4095,0,(struct sockaddr*)&client_addr,&len);
    if(ret<0)
    {
      close(sockfd);
      perror("recvfrom error");
      return -1;
    }
    printf("%s:%d - %s\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),buf);
    printf("server input");
    fflush(stdout);
    memset(buf,0x00,4096);
    scanf("%s",buf);
    ret=sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&client_addr,len);
    if(ret<0)
    {
      close(sockfd);
      perror("sendto error");
      return -1;
    }
  }
  close(sockfd); 
 return 0;
}
sockaddr_in Members of the struct in_addr sin_addr Express 32 position Of IP Address
But we usually use dotted decimal strings to represent IP Address , The following functions can be represented in a string and in_addr Conversion between representations ;
String rotation in_addr Function of
in_addr Functions that convert strings

  among inet_pton and inet_ntop Not only can it be converted IPv4 Of in_addr, You can also convert IPv6 Of in6_addr, So the function interface is void *addrptr.

encapsulation TCPSocket

#include<cstdio>
#include<iostream>

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

#define MAX_LISTEN 5
#define CHECK_RET(q) if((q)==false){return -1;}
class TcpSocket
{
  public:
    TcpSocket()
      :_sockfd(-1)
    {}
    bool Socket()
    {
      _sockfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
      if(_sockfd<0)
      {
        perror("socket error");
        return false;
      }
      return true;
    }
    bool Bind(const std::string&ip,int port)
    {
      struct sockaddr_in addr;
      addr.sin_family=AF_INET;
      addr.sin_port=htons(port);
      addr.sin_addr.s_addr=inet_addr(ip.c_str());
      socklen_t len=sizeof(addr);
      if(bind(_sockfd,(struct sockaddr*)&addr,len)<0)
      {
        perror("bind error");
        return false;
      }
      return true;
    }
    bool Listen(int backlog=MAX_LISTEN)
    {
      if(listen(_sockfd,backlog)<0)
      {
        perror("listen error");
        return false;
      }
      return true;
    }
    bool Connect(const std::string &srv_ip,int srv_port)
    {
      struct sockaddr_in addr;
      addr.sin_family=AF_INET;
      addr.sin_port=htons(srv_port);
      addr.sin_addr.s_addr=inet_addr(srv_ip.c_str());
      socklen_t len=sizeof(addr);
      if(connect(_sockfd,(struct sockaddr*)&addr,len)<0)
      {
        perror("connect error");
        return false;
      }
      return false;
    }
    bool Accept(TcpSocket *new_sock,std::string *cli_ip,int *cli_port)
    {
      struct sockaddr_in addr;
      socklen_t len=sizeof(addr);
      int newfd=accept(_sockfd,(struct sockaddr*)&addr,&len);
      if(newfd<0)
      {
        perror("accept error");
        return false;
      }
      std::cout<<"new connect:"<<inet_ntoa(addr.sin_addr)<<":"<<ntohs(addr.sin_port)<<"\n";
      new_sock->_sockfd=newfd;
      if(cli_ip!=NULL)
      {
        *cli_ip=inet_ntoa(addr.sin_addr);
      }
      if(cli_port!=NULL)
      {
        *cli_port=ntohs(addr.sin_port);
      }
      return true;
    }
    bool Send(const std::string &data)
    {
      ssize_t ret=send(_sockfd,data.c_str(),data.size(),0);
      {
        if(ret<0)
        {
          perror("send error");
          return false;
        }
        return true;
      }
    }
    bool Recv(std::string *buf)
    {
      char tmp[4096]={0};
      ssize_t ret=recv(_sockfd,tmp,4096,0);
      if(ret<0)
      {
        perror("recv error");
        return false;
      }
      else if(ret==0)
      {
        std::cout<<"perr shutdown!\n";
        return false;
      }
      buf->assign(tmp,ret);// from tmp Intercept data of specified length , Prevent the end of string mark in the data ;
      return true;
    }
    bool Close()
    {
      if(_sockfd>0)
      {
        close(_sockfd);
        _sockfd=-1;
      }
      return true;
    }

  private:
    int _sockfd;

};

tcp Server side

#include"tcp_socket.cpp"
int main(int argc,char *argv[])
{
  if(argc<2)
  {
    std::cout<<"usage: ./tcp_srv 9000\n";
    return -1;
  }
  int port = std::stoi(argv[1]);
  // Create socket 
  TcpSocket lst_sock;
  CHECK_RET(lst_sock.Socket());
  // Binding address information 
  CHECK_RET(lst_sock.Bind("0.0.0.0",port));
  // Start listening 
  CHECK_RET(lst_sock.Listen());
  while(1)
  {
    TcpSocket new_sock;
    std::string cli_ip;
    int cli_port;
    CHECK_RET(lst_sock.Accept(&new_sock,&cli_ip,&cli_port));
    std::cout<<"new connect: "<<cli_ip<<":"<<cli_port<<"\n";
    std::string buf;
    new_sock.Recv(&buf);// Communicate with the specified client by creating a new connection 
    std::cout<<"client say: "<<buf<<std::endl;
    buf.clear();
    std::cout<<"server say: ";
    std::cin>>buf;
    new_sock.Send(buf);
  }
  lst_sock.Close();
  return 0;
}

 tcp client

#include"tcp_socket.cpp"
int main(int argc,char*argv[])
{
  // Although the client does not actively bind addresses , But you must know the address of the server ;
  if(argc<3)
  {
    std::cout<<"usage: arg error\n";
    std::cout<<"\t ./tcp_cli 192.168.2.2 9000\n";
    return -1;
  }
  int srv_port=std::stoi(argv[2]);
  std::string srv_ip=argv[1];
  TcpSocket sock;
  // Create socket 
  CHECK_RET(sock.Socket());
  // Send a connection request to the server 
  CHECK_RET(sock.Connect(srv_ip,srv_port));
  while(1)
  {
    std::string data;
    std::cout<<"client say:";
    fflush(stdout);
    std::cin>>data;
    sock.Send(data);
    CHECK_RET(sock.Send(data));
    data.clear();
    CHECK_RET(sock.Recv(&data));
    std::cout<<"server say:"<< data<<std::endl;
  }
 //  Close socket 
 sock.Close();
}

原网站

版权声明
本文为[Exy-]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202130620440755.html