Linux网络编程之搭建服务器和客户端(一)

2022-03-21 09:14:55 浏览数 (1)

前言

昨天介绍完了网络编程中常用的api接口使用方法,今天我们开始来进行实战编程学习!

搭建服务器和客户端编程

- IP地址转换实战演示 -

1、首先我们来演示inet_addr这个函数来对ip地址转换:

代码语言:javascript复制
 #include <stdio.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>

 #define  IPADDR   "192.168.1.102"

 int main(void)
{

     in_addr_t addr = 0;
     addr=inet_addr(IPADDR);
     printf("the addr is 0x%xn",addr);


     return 0;

 }

演示结果:

代码语言:javascript复制
 ubuntu@ubuntu-virtual-machine:~$ ./a.out
 the addr is 0x6601a8c0

说明:这里我们可以看到IP地址点分十进制表示方法被转换成一般形式(这里打印出的是十六进制表示法)。

2、inet_pton对IP地址转换演示:

代码语言:javascript复制
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define  IPADDR   "192.168.1.102"

int main(void)
{
   int net =0;
   struct in_addr addr;
   net=inet_pton(AF_INET,IPADDR,&addr.s_addr);
   if(1!=net)
   {
      printf("the inet_pton is errorn");
      return -1;
   }
      printf("the addr is = 0x%xn",addr.s_addr);

      return 0;

}

演示结果:

代码语言:javascript复制
ubuntu@ubuntu-virtual-machine:~$ ./a.out
the addr is = 0x6601a8c0

说明:效果和inet_addr函数一样。

3、inet_ntop对IP地址转换:

代码语言:javascript复制
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(void)
{

    char buf[50]={0};
    const char *net =NULL;
    struct in_addr addr;
    addr.s_addr= 0x6703a8c0;

    net=inet_ntop( AF_INET,&addr.s_addr,buf,sizeof(buf));
    if(NULL==net)
    {
        printf("the inet_ntop is errorn");
        return -1;
    }

        printf("the addr is %sn",buf);
        return 0;

  }

演示结果:

代码语言:javascript复制
ubuntu@ubuntu-virtual-machine:~$ ./a.out
the addr is 192.168.3.103

说明:这里我们可以看到inet_ntop函数把一般的形式的IP地址转换成点分十进制。

- 搭建服务器 -

  • 第一步:调用socket函数来创建套接字。
  • 第二步:调用bind函数分配IP地址和端口号。
  • 第三步:调用listen函数转为可接收状态。
  • 第四步:调用accept函数来处理连接请求。 返回值是一个fd,accept正确返回就表示我们已经和前来连接我的客户端之间建立了一个TCP连接了,以后我们就要通过这个连接来和客户端进行读写操作,读写操作就需要一个fd,这个fd就由accept来返回了,跟我们之前的socketfd是不一样的,这一点要注意。
  • 第五步:关闭套接字文件描述符。
  • 注意:socket返回的fd叫做监听fd,是用来监听客户端的,不能用来和任何客户端进行读写;accept返回的fd叫做连接fd,用来和连接那端的客户端程序进行读写。
代码语言:javascript复制
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>



#define SERPORT        9003
#define SERADDR        "192.168.183.140"        
// ifconfig看到的
#define BACKLOG        100


int main(void)
{
       // 第1步:先socket打开文件描述符
       int sockfd = -1, ret = -1, clifd = -1;
       socklen_t len = 0;
       struct sockaddr_in seraddr = {0};
       struct sockaddr_in cliaddr = {0};

        //char ipbuf[30] = {0};


       sockfd = socket(AF_INET, SOCK_STREAM, 0);
       if (-1 == sockfd)
       {
             perror("socket");
             return -1;
        }
       printf("socketfd = %d.n", sockfd);

      // 第2步:bind绑定sockefd和当前电脑的ip地址&端口号
      seraddr.sin_family = AF_INET;     // 设置地址族为IPv4
      seraddr.sin_port = htons(SERPORT);    // 设置地址的端口号信息
      seraddr.sin_addr.s_addr = inet_addr(SERADDR); // 设置IP地址
      ret = bind(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));
     if (ret < 0)
    {
          perror("bind");
          return -1;
    }
    printf("bind success.n");

    // 第三步:listen监听端口
    ret = listen(sockfd, BACKLOG);      
    if (ret < 0)
    {
       perror("listen");
       return -1;
    }

    // 第四步:accept阻塞等待客户端接入
   clifd = accept(sockfd, (struct sockaddr *)&cliaddr, &len);
   printf("连接已经建立,client fd = %d.n", clifd );

   return 0;
}

说明:上面的服务器的IP地址要根据每个人的电脑来查看(可以使用ifconfig查看,如下买所示),还有函数htons(它表示表示把主机地址转化为网络讯流,这样看到这个函数就知道它的意思,h——表示host,n——表示network,s表示short,就是字节大小,其实通信也要有大小端模式的,就是说双方通信要规定好是同一模式就好,关于大小端模式的介绍,可以看之前的文章——c语言之共用体union、枚举、大小端模式,如下所示):

代码语言:javascript复制
  root@ubuntu-virtual-machine:/home/ubuntu# ifconfig
  ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
    inet 192.168.183.140  netmask 255.255.255.0  
    broadcast 192.168.183.255
    inet6 fe80::6b81:110c:548f:2f41  prefixlen 64  
scopeid 0x20<link>
代码语言:javascript复制
   #include <arpa/inet.h>

   uint32_t htonl(uint32_t hostlong);

   uint16_t htons(uint16_t hostshort);

   uint32_t ntohl(uint32_t netlong);

   uint16_t ntohs(uint16_t netshort);

DESCRIPTION
    The htonl() function converts the unsigned integer 
   hostlong  from  host
   byte order to network byte order.

   The htons() function converts the unsigned short 
   integer hostshort from
   host byte order to network byte order.

   The ntohl() function converts the unsigned integer 
   netlong from network
   byte order to host byte order.

   The  ntohs() function converts the unsigned short 
   integer netshort from
   network byte order to host byte order.

   On the i386 the host  byte  order  is  Least  
   Significant  Byte  first,
   whereas  the  network byte order, as used on the 
   Internet, is Most Sig‐
   nificant Byte first.

- 客户端 -

  • socket,先创建套接字。
  • connect,用来连接服务器的。
代码语言:javascript复制
 #include <stdio.h>
 #include <sys/socket.h>
 #include <sys/types.h>          /* See NOTES */
 #include <sys/socket.h>
 #include <arpa/inet.h>


 #define SERADDR        "192.168.183.140"         // 服务器开放给我们的IP地址和端口号
 #define SERPORT        9003



int main(void)
{
     // 第1步:先socket打开文件描述符
     int sockfd = -1, ret = -1;
     struct sockaddr_in seraddr = {0};
     struct sockaddr_in cliaddr = {0};

     // 第1步:socket
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == sockfd)
    {
        perror("socket");
        return -1;
    }
   printf("socketfd = %d.n", sockfd);

    // 第2步:connect链接服务器
   seraddr.sin_family = AF_INET;        // 设置地址族为IPv4
   seraddr.sin_port = htons(SERPORT);   // 设置地址的端口号信息
   seraddr.sin_addr.s_addr = inet_addr(SERADDR);    // 设置IP地址
  ret = connect(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));
  if (ret < 0)
  {
       perror("listen");
       return -1;
  }
  printf("connect result, ret = %d.n", ret);


   return 0;
}

最终结果(这里只是暂时实现服务器和客户端通信,后面再实现更多功能):

0 人点赞