基于流式套接字Socket的C/S通信设计(一)

一、基本目标

        实现简单通信。读取配置文件以连接服务器并实现简单登录功能。

二、流程实现

三、详细设计

服务端

        常用Socket函数详解

 1、socket()

       实现网络进程通信,在Linux/Unix“一切皆文件”的思想中实现“open、write/read、close”模式。可将其视作一种特殊的文件。

int sock_fd = socket(AF_INET, SOCK_STREAM, 0);    //AF_INET:IPV4;    SOCK_STREAM:TCP

2、bind()

        当socket函数返回一个描述符时,只是存在于其协议族的空间中,并没有分配一个具体的协议地址(这里指IPv4/IPv6和端口号的组合),bind函数可以将一组固定的地址绑定到sockfd上。


struct sockaddr_in server_addr;    //服务器地址
memset(&server_addr, 0, sizeof(struct sockaddr_in));    //初始化
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);    //INADDR_ANY:This machine all IP
bind(sock_fd, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr));


3、listen()

        当socket函数创建一个套接字时,它被假设为一个主动套接字,也就是说,它是一个将调用connect连接的客户套接字。listen函数把一个未连接的套接字转换成一个被动套接字,指示内核应该接受指向该套接字的连接请求。如下图所示,调用listen导致套接字从CLOSED状态转换到LISTEN状态。
————————————————
版权声明:本文为CSDN博主「godop」的原创文章,遵循CC 4.0 BY-SA版权协议。
原文链接:https://blog.csdn.net/godop/article/details/79894079

listen(sock_fd, BA
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是基于的 C/S 通信程序的代码,实现了客户端向服务器发送一个简单的四则算(只含一个算符),服务器收到这个算后,对其进行计算,并将计算结果回送给客户端,客户端将计算结果显示出来。 服务器端代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #define PORT 8080 int main() { int server_fd, new_socket, valread; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[1024] = {0}; // 创建 socket 文件描述符 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 设置 socket 选项 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); // 绑定 socket 到指定的地址和端口号 if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听连请求 if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } // 受客户端连请求 if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0) { perror("accept"); exit(EXIT_FAILURE); } // 从客户端收算并进行计算 valread = read(new_socket, buffer, 1024); int num1, num2, result; char op; sscanf(buffer, "%d%c%d", &num1, &op, &num2); switch (op) { case '+': result = num1 + num2; break; case '-': result = num1 - num2; break; case '*': result = num1 * num2; break; case '/': result = num1 / num2; break; default: result = 0; break; } printf("Received equation from client: %d %c %d\n", num1, op, num2); printf("Calculated result: %d\n", result); // 将计算结果发送给客户端 char result_str[1024]; sprintf(result_str, "%d", result); send(new_socket, result_str, strlen(result_str), 0); return 0; } ``` 客户端代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #define PORT 8080 int main(int argc, char const *argv[]) { int sock = 0, valread; struct sockaddr_in serv_addr; char buffer[1024] = {0}; // 创建 socket 文件描述符 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("\n Socket creation error \n"); return -1; } // 设置服务器地址和端口号 serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); // 将点分十进制 IP 地址转换为二进制格 if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) { printf("\nInvalid address/ Address not supported \n"); return -1; } // 连到服务器 if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { printf("\nConnection Failed \n"); return -1; } // 向服务器发送算 char equation[1024]; printf("Enter equation: "); scanf("%s", equation); send(sock, equation, strlen(equation), 0); printf("Equation sent to server: %s\n", equation); // 收服务器发送的计算结果 valread = read(sock, buffer, 1024); printf("Result received from server: %s\n", buffer); return 0; } ``` 编译并运行: 首先编译服务器端代码: ```bash gcc server.c -o server ``` 然后编译客户端代码: ```bash gcc client.c -o client ``` 着先运行服务器端程序: ```bash ./server ``` 最后运行客户端程序: ```bash ./client ``` 运行客户端程序后,会提示输入算,输入完毕后程序会将算发送给服务器,服务器会对算进行计算,并将计算结果发送给客户端,客户端收到计算结果后将其显示出来。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

LeoMove

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

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

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

打赏作者

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

抵扣说明:

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

余额充值