【Linux网络编程】服务端编程初体验

简介: 【Linux网络编程】服务端编程初体验

前言

在上节课(Linux网络编程初体验)中我们实现了连接bilibili的功能,并获取其html源码

abf4298d4a1f4f71841977fdbcd7eb82.png

如图所示.

今天我们要自己编写个服务端来服务我们的客户端


提示:以下是本篇文章正文内容,下面案例可供参考

服务端是啥、有什么特点

服务端长期暴露于网络,并等待客户端连接

特点:

服务端无法主动连接客户端

客户端只能按照预定义的方式连接服务端

服务端编程模式:

socket()->bind()->listen()->accept()->client_sock->
send()/recv->close()

核心函数

int bind(int sock,struct sockaddr*addr,socklen_t addrlen);//参数1:服务端sock,参数2:服务端sockaddr,参数3:参数2的大小,类型为socklen_t
int listen(int sock,int backlog);//参数1:服务端sock,参数2:直接填1
int accept(int sock,struct sockaddr*addr,socklen_t*addrlen);//参数1:客户端sock,参数2接受客户端addr的地址,参数3:参数2的长度

accept()的返回值为客户端的sock

socket的简介

服务端socket只用于连接,不进行通讯

服务端的socket用于产生客户端的socket

socket还可以提供不同类型的通信功能(本地、局域网等)

服务器编程

头文件:

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

定义服务端的socket和sockaddr_inint server = 0; struct sockaddr_in saddr = {0};

定义要通信的客户端的socket和sockaddr_inint client = 0; struct sockaddr_in caddr = {0};

定义客户端sockaddr_in 的长度变量socklen_t asize = 0;

以及其他的变量

  int len = 0;//发送和接收的字符串长度
    char buf[32] = {0};//接收区
    int r = 0;//循环控制变量

创建socket

  server = socket(PF_INET, SOCK_STREAM, 0);
    if( server == -1 )
    {
        printf("server socket error\n");
        return -1;
    }

赋值服务端的sockaddr_in

  saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY:同一wifi下的主机地址都可以
    saddr.sin_port = htons(8899);

绑定以及监听

  if( bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1 )
    {
        printf("server bind error\n");
        return -1;
    }
    if( listen(server, 1) == -1 )
    {
        printf("server listen error\n");
        return -1;
    }

等待客户端的连接

  while(1)
  {
    asize = sizeof(caddr);//客户端sockaddr_in大小
      client = accept(server, (struct sockaddr*)&caddr, &asize);
      if( client == -1 )
      {
           printf("client accept error\n");
         return -1;
      }
    printf("client: %d\n", client);
  }

接收和发送数据:

    do
        {
            r = recv(client, buf, sizeof(buf), 0);
            if( r > 0 )
            {
                printf("Receive: %s\n", buf);
                if( strcmp(buf, "quit") != 0 )//当字符串为quit时,退出
                {
                    len = send(client, buf, r, 0);
                    break;
                }
                else
                {
                    break;
                }
            }
        } while ( r > 0 );

注意:这里的代码在while(1)里面

代码全貌:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
    int server = 0;
    struct sockaddr_in saddr = {0};
    int client = 0;
    struct sockaddr_in caddr = {0};
    socklen_t asize = 0;
    int len = 0;server
    char buf[32] = {0};
    int r = 0;
    server = socket(PF_INET, SOCK_STREAM, 0);
    if( server == -1 )
    {
        printf("server socket error\n");
        return -1;
    }
    saddr.sin_fami0ly = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    saddr.sin_port = htons(8888);
    if( bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1 )
    {
        printf("server bind error\n");
        return -1;
    }
    if( listen(server, 1) == -1 )
    {
        printf("server listen error\n");
        return -1;
    }
    printf("server start success\n");
    while( 1 )
    {
        asize = sizeof(caddr);
        client = accept(server, (struct sockaddr*)&caddr, &asize);
        if( client == -1 )
        {
            printf("client accept error\n");
            return -1;
        }
        printf("client: %d\n", client);
        do
        {
            r = recv(client, buf, sizeof(buf), 0);
            if( r > 0 )
            {
                printf("Receive: %s\n", buf);
                if( strcmp(buf, "quit") != 0 )
                {
                    len = send(client, buf, r, 0);
                    break;
                }
                else
                {
                    break;
                }
            }
        } while ( r > 0 );
        close(client);
    }
    close(server);
    return 0;
}

客户端代码

复用上期的服务端

改动:

1、定义input变量,让用户自己输入字符发送给服务端char input[32] = {0};

2、端口号和ip地址

ip地址:在TerMinal中输入ifconfig可以看到ip地址。如下图

4a202c9343284922884b02095efac80c.png

端口号:要和服务器中的一样(8899)

收发数据代码:

  while(1)
  {
      printf("Input: ");
          scanf("%s", input);
          len = send(sock, input, strlen(input) + 1, 0);
          r = recv(sock, buf, sizeof(buf), 0);
          if( r > 0 )
          {
              printf("Receive: %s\n", buf);
          }
          else
          {
              break;
          }
        }

客户端代码全貌:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
    int sock = 0;
    struct sockaddr_in addr = {0};
    int len = 0;
    char buf[128] = {0};
    char input[32] = {0};
    int r = 0;
    sock = socket(PF_INET, SOCK_STREAM, 0);
    if( sock == -1 )
    {
        printf("socket error\n");
        return -1;
    }
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr("192.168.254.128");
    addr.sin_port = htons(8899);
    if( connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1 )
    {
        printf("connect error\n");
        return -1;
    }
    printf("connect success\n");
    while( 1 )
    {
        printf("Input: ");
        scanf("%s", input);
        len = send(sock, input, strlen(input) + 1, 0);
        r = recv(sock, buf, sizeof(buf), 0);
        if( r > 0 )
        {
            printf("Receive: %s\n", buf);
        }
        else
        {
            break;
        }
    }
    close(sock);
    return 0;
}

The End

大家可以使用下面2个命令编译我们写好的东西:

gcc -o 编译后的文件名.o 编译的文件名.c
./编译后的文件名.o

注意:要先开服务端!!!

相关文章
|
12月前
|
运维 Linux 开发者
Linux系统中使用Python的ping3库进行网络连通性测试
以上步骤展示了如何利用 Python 的 `ping3` 库来检测网络连通性,并且提供了基本错误处理方法以确保程序能够优雅地处理各种意外情形。通过简洁明快、易读易懂、实操性强等特点使得该方法非常适合开发者或系统管理员快速集成至自动化工具链之内进行日常运维任务之需求满足。
703 18
|
11月前
|
安全 Linux 网络安全
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
279 0
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
|
12月前
|
网络协议 关系型数据库 Linux
【App Service Linux】在Linux App Service中安装 tcpdump 并抓取网络包
在App Service for Linux环境中,无法像Windows一样直接使用网络排查工具抓包。本文介绍了如何通过TCPDUMP在Linux环境下抓取网络包,包括SSH进入容器、安装tcpdump、执行抓包命令及下载分析文件的完整操作步骤。
528 5
|
Web App开发 网络协议 Linux
【Linux】网络基础
TCP/IP五层模型是网络通信的基础框架,将复杂的数据传输过程分为物理层、数据链路层、网络层、传输层和应用层,每层各司其职,协同完成远程通信。该模型确保了不同设备和网络之间的互联互通,是现代互联网运行的核心机制。
1388 5
|
安全 网络协议 Linux
Linux网络应用层协议展示:HTTP与HTTPS
此外,必须注意,从HTTP迁移到HTTPS是一项重要且必要的任务,因为这不仅关乎用户信息的安全,也有利于你的网站评级和粉丝的信心。在网络世界中,信息的安全就是一切,选择HTTPS,让您的网站更加安全,使您的用户满意,也使您感到满意。
441 19
|
安全 算法 Ubuntu
Linux(openssl)环境:编程控制让证书自签的技巧。
总结:在Linux环境中,OpenSSL是一个非常实用的工具,可以帮助我们轻松地生成自签名证书。通过上述三个简单步骤,即可为内部网络、测试环境或开发环境创建自签名证书。但在公共访问场景下,建议购买经过权威认证机构签发的证书,以避免安全警告。
751 13
|
Linux 数据安全/隐私保护
使用Linux命令行接入无线网络Wi-Fi的示例。
现在,你已经使用命令行成功地连接到 Wi-Fi 网络了。这两个示例涵盖了用 `nmcli` 和 `wpa_supplicant` 连接无线网络的常见场景,让你能够不依赖图形化界面来完成这个任务。在日常使用中熟练掌握这些基本操作能增强你对 Linux 系统的理解,帮助你更有效地处理各种问题。
1169 12
|
网络协议 Linux 开发者
深入Linux中UDP网络通信机制编程探索
以上步骤概述了Linux中UDP网络通信的编程机制。在实现时,因关注细节和上下文环境可能有所调整,但大致流程是一致的。这些知识片段旨在帮助开发者快速上手Linux下的UDP编程,并提供可靠的信息作为编程的基础。在编程实践中,应结合实际业务需求,设计合适的数据传输协议,确保数据的正确性和实时性。
267 0
|
Ubuntu Linux
Linux系统管理:服务器时间与网络时间同步技巧。
以上就是在Linux服务器上设置时间同步的方式。然而,要正确运用这些知识,需要理解其背后的工作原理:服务器根据网络中的其他机器的时间进行校对,逐步地精确自己的系统时间,就像一只犹豫不决的啮齿动物,通过观察其他啮齿动物的行为,逐渐确定自己的行为逻辑,既简单,又有趣。最后希望这个过程既能给你带来乐趣,也能提高你作为系统管理员的专业素养。
2431 20
|
安全 Ubuntu Linux
Nipper 3.8.0 for Windows & Linux - 网络设备漏洞评估
Nipper 3.8.0 for Windows & Linux - 网络设备漏洞评估
679 0
Nipper 3.8.0 for Windows & Linux - 网络设备漏洞评估

热门文章

最新文章