在Linux系统实现服务器端和客户端的套接字通信

目录

一.创建一个socket文件夹用来存放编写的服务器端和客户端程序

二.编写服务器端代码

三.编写客户端代码

四.编译c语言程序

五.断开连接

六.可能涉及到的一些没接触过的知识点

一.创建一个socket文件夹用来存放编写的服务器端和客户端程序

(我系统里的文件在temp/socket$文件夹中)

 

二.编写服务器端代码

vim server.c

在server.c中编写的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>//提供IP地址转换函数

int main()
{
    //1.创建监听的套接字
    int fd = socket(AF_INET,SOCK_STREAM, 0);
    if (fd == -1)
    {
        perror("socket");//perror(s) 用来将上一个函数发生错误的原因输出到标准设备,参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno的值来决定要输出的字符串。
        return -1;
    }

    //2.绑定本地的IP port
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;//地址族协议
    saddr.sin_port = htons(9999);//端口必须转换成大端
    saddr.sin_addr.s_addr = INADDR_ANY;//指定IP地址(INADDR_ANY泛指本机的意思,也就是表示本机的所有IP)
    int ret = bind(fd, (struct sockaddr*)&saddr, sizeof(saddr));
    if (ret == -1)//绑定失败 返回-1
    {
        perror("bind");
        return -1;
    }
    //3设置监听
    ret = listen(fd, 128);
    if (ret == -1)
    {
        perror("listen");
        return -1;
    }
    //4阻塞并等待客户端的连接
    struct sockaddr_in caddr;
    int addrlen = sizeof(caddr);
    int cfd = accept(fd, (struct sockaddr*)&caddr,&addrlen );
    if (cfd == -1)
    {
        perror("accept");
        return -1;
    }
    //连接建立成功,打印客户端的IP和端口信息
    char ip[32];
    printf("客户端的ip:%s,端口:%d\n",
        inet_ntop(AF_INET, &caddr.sin_addr.s_addr, ip, sizeof(ip)), ntohs(caddr.sin_port));//网络字节序转换为主机字节序
   
    //5.通信
    while (1)
    {
        //接收数据
        char buff[1024];
        int len = recv(cfd, buff, sizeof(buff), 0);
        if (len > 0)
        {
            printf("client say: %s\n", buff);
            send(cfd, buff, len, 0);
        }
        else if (len == 0)
        {
            printf("客户端已经断开了连接...\n");
            break;
        }
        else
        {
            perror("recv");
            break;
        }
    }
    //关闭文件描述符
    close(fd);
    close(cfd);
    return 0;
}

三.编写客户端代码

vim client.c

在client中编写的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>//提供IP地址转换函数

int main()
{
    //1.创建通信的套接字
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd == -1)
    {
        perror("socket");//perror(s) 用来将上一个函数发生错误的原因输出到标准设备,参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno的值来决定要输出的字符串。
        return -1;
    }

    //2.连接服务器IP port
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;//地址族协议
    saddr.sin_port = htons(9999);//端口必须转换成大端
    inet_pton(AF_INET, "192.168.122.1 ", &saddr.sin_addr.s_addr);
    int ret = connect(fd, (struct sockaddr*)&saddr, sizeof(saddr));
    if (ret == -1)//连接失败 返回-1
    {
        perror("connect");
        return -1;
    }
    
    int number = 0;
    //3.通信
    while (1)
    {
        //发送数据
        char buff[1024];
        sprintf(buff, "你好,hello ,world ,%d...\n", number++);
        send(fd, buff, strlen(buff) + 1, 0);
        //接收数据
        memset(buff, 0, sizeof(buff));
        int len = recv(fd, buff, sizeof(buff), 0);
        if (len > 0)
        {
            printf("server say: %\n", buff);

        }
        else if (len == 0)
        {
            printf("服务器端已经断开了连接...\n");
            break;
        }
        else
        {
            perror("recv");
            break;
        }
        sleep(1);
    }
    //关闭文件描述符
    close(fd);
    return 0;
}

四.编译c语言程序

[itliang@localhost socket]$ gcc client.c -o client
[itliang@localhost socket]$ gcc server.c -o server

 运行server.c程序,先运行服务器端再运行客户端

 运行client.c程序,至此客户端与服务器端建立通信,客户端收到服务器端消息,并输出“你好,hello,world”

 

 服务器端收到客户端消息,并输出“你好,hello,world”

 五.断开连接

当服务器端断开连接时,客户端会显示“服务器端已经断开了连接”

 当客户端断开连接时,服务器端会显示“客户端已经断开了连接”

 

 六.可能涉及到的一些没接触过的知识点

perror(s)函数

        用来将上一个函数发生错误的原因输出到标准设备(stderr)。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno的值来决定要输出的字符串。

sockaddr_in在头文件#include<netinet/in.h>或#include <arpa/inet.h>中定义,该结构体解决了sockaddr的缺陷,把port和addr 分开储存在两个变量中,如下:

 

GCC 是 Linux 下的编译工具集,是 GNU Compiler Collection 的缩写,包含 gcc、g++ 等编译器。这个工具集不仅包含编译器,还包含其他工具集,例如 ar、nm 等。

        GCC 工具集不仅能编译 C/C++ 语言,其他例如 Objective-C、Pascal、Fortran、Java、Ada 等语言均能进行编译。GCC 在可以根据不同的硬件平台进行编译,即能进行交叉编译,在 A 平台上编译 B 平台的程序,支持常见的 X86、ARM、PowerPC、mips 等,以及 Linux、Windows 等软件平台。
        有些纯净版的 Linux 默认没有 gcc 编译器,需要自己安装,在线安装步骤如下:

# 安装软件必须要有管理员权限
# ubuntu
$ sudo apt update           # 更新本地的软件下载列表, 得到最新的下载地址
$ sudo apt install gcc g++    # 通过下载列表中提供的地址下载安装包, 并安装

# centos
$ sudo yum update           # 更新本地的软件下载列表, 得到最新的下载地址
$ sudo yum install gcc g++    # 通过下载列表中提供的地址下载安装包, 并安装
gcc 安装完毕之后,可以查看版本:


# 查看 gcc 版本
$ gcc -v
$ gcc --version

# 查看 g++ 版本
$ g++ -v
$ g++ --version

编译:

# 参数 -c 是进行文件的汇编, 汇编之前的两步会自动执行
$ gcc test.c -c -o app.o

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小梁今天敲代码了吗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值