当前位置:   article > 正文

TCP网络编程----C/S模型 (客户端/服务器模型)的代码实现_客户端代码和服务器端代码

客户端代码和服务器端代码

TCP网络编程----C/S模型 (客户端/服务器模型)的代码实现

client发送数据到server,server对数据进行提取并根据用户输入的操作符进行两个数的计算,并将计算结果传给client。(实际上,这个例子已经有了云计算的雏形)


前言

本文章使用的是Ubuntu操作系统和C语言实现了简单的客户端(client)和服务器端(server)的通信。

本文代码实现所需要用到的头文件如下:

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

一、TCP网络编程流程

在这里插入图片描述

服务器流程:

1.创建套接字
2.填充服务器的网络信息结构体
3.将套接字和服务器的网络信息结构体绑定
4.把套接字设置成被动监听状态
5.阻塞等待客户端连接
6.收发数据
7.关闭套接字

客户端流程:

1.创建套接字
2.填充服务器的网络信息结构体
3.与服务器建立连接
4.收发数据
5.关闭套接字

二、代码实现

1.服务器代码实现

#include <net_head.h>
/*
功能:	根据客户端传入的数据进行计算(两个数的计算)
参数:
    @buf:从客户端接收的数据,存放的buf数组的首地址
    @len:数组的长度
返回值:	成功返回计算的结果
*/
int calculate(char* buf, int len)
{
    int lvalue = 0;
    int rvalue = 0;
    char operator;
    int i = 0;
    int ret = 0;
    //(1) 循环找到第一个数字的位置
    while ((buf[i] < '0' || buf[i] > '9') && i < len)
        i++;

    //(2) 从第一个数字的位置往后找一串数字,作为左操作数
    for (; buf[i] >= '0' && buf[i] <= '9' && i < len; i++) {
        lvalue *= 10;
        lvalue += buf[i] - '0';
    }

    //(3) 循环找运算符
    for (; buf[i] != '+' && buf[i] != '-' && buf[i] != '*' && buf[i] != '/' && buf[i] != '%' && i < len; i++) {
        printf("%c", buf[i]);
    }
    operator= buf[i];

    //(4) 循环找右操作数开头的第一个数字
    while ((buf[i] < '0' || buf[i] > '9') && i < len)
        i++;

    //(5) 从第一个数字的位置往后找一串数字,作为右操作数
    for (; buf[i] >= '0' && buf[i] <= '9' && i < len; i++) {
        rvalue *= 10;
        rvalue += buf[i] - '0';
    }

    printf("%d %c %d\n", lvalue, operator, rvalue);

    //(6) 根据操作符做运算
    switch (operator) {
    case '+':
        ret = lvalue + rvalue;
        break;
    case '-':
        ret = lvalue - rvalue;
        break;
    case '*':
        ret = lvalue * rvalue;
        break;
    case '/':
        ret = lvalue / rvalue;
        break;
    case '%':
        ret = lvalue % rvalue;
        break;
    default:
        printf("Input error\n");
        break;
    }

    return ret;
}

int main(int argc, const char* argv[])
{
    // 1.创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket error");
        exit(-1);
    }

    // 2.填充服务器的网络信息结构体
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr("这里填server端虚拟机的ip地址");
    serverAddr.sin_port = htons(这里填任意一个合适的端口号);

    // 3.将套接字和服务器的网络信息结构体绑定
    socklen_t serverAddr_len = sizeof(serverAddr);
    if (-1 == bind(sockfd, (struct sockaddr*)&serverAddr, serverAddr_len)) {
        perror("bind error");
        exit(-1);
    }

    // 4.把套接字设置成被动监听状态
    if (-1 == listen(sockfd, 5)) {
        perror("listen error");
        exit(-1);
    }

    // 5.阻塞等待客户端连接
    // int acceptfd = accept(sockfd, (struct sockaddr*)&serverAddr, &serverAddr_len);//error
    int acceptfd = accept(sockfd, NULL, NULL);
    if (acceptfd == -1) {
        perror("accept error");
        exit(-1);
    }

    // 6.接收数据,并作两个数的计算
    char buf[128] = "";
    int len = sizeof(buf);

    read(acceptfd, buf, sizeof(buf));
    int ret = calculate(buf, len);

    // 7.发送数据
    write(acceptfd, &ret, sizeof(ret));

    // 8.关闭套接字
    close(acceptfd);
    close(sockfd);

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120

2.客户端代码的实现

#include <net_head.h>

int main(int argc, const char* argv[])
{

    // 1.创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket error");
        exit(-1);
    }

    // 2.填充服务器的网络信息结构体
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr("这里填server端主机的IP地址");
    serverAddr.sin_port = htons(这里填任意一个合适的端口号,eg:7777,server端配置端口转发的时候,也要填这个端口号);

    // 3.与服务器简历连接
    if (-1 == connect(sockfd, (const struct sockaddr*)&serverAddr, sizeof(serverAddr))) {
        perror("connect error");
        exit(-1);
    }
    printf("Connected to server..\n");

    // 4.发送数据
    char buf[128] = "";
    printf("Please input : ");
    fgets(buf, sizeof(buf), stdin);
    buf[strlen(buf) - 1] = '\0';

    write(sockfd, buf, sizeof(buf));

    // 5.接收数据
    int ret = 0;
    read(sockfd, &ret, sizeof(ret));
    printf("From server : result is >> %d\n", ret);

    // 6.关闭套接字
    close(sockfd);

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

三、两台不同虚拟机之间的通信

注意事项:

本文使用的是VMware软件,对于端口转发的配置,有以下3点注意事项:
	1.服务器端要关闭防火墙!
 	2.client代码中的ip地址要写server端的主机ip(注意不是虚拟机ip)
    3.server端所在的主机要配置端口转发:端口号和client代码中的端口号要保持一致):
  • 1
  • 2
  • 3
  • 4

结果展示

server端

client端:

在这里插入图片描述


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/144090?site
推荐阅读
相关标签
  

闽ICP备14008679号