手写服务器与手写客户端相连接-qwen

USER

手写服务器与手写客户端相连接

ASSISTANT

好的,我们可以使用 C 语言和 POSIX Sockets API 来实现一个基础的 TCP 服务器和客户端。这个示例将展示它们如何建立连接、发送和接收消息。

核心思路:

  1. 服务器 (Server):
    • 创建一个监听套接字 (socket)。
    • 将该套接字绑定 (bind) 到一个特定的 IP 地址和端口。
    • 开始监听 (listen) 该端口上的连接请求。
    • 接受 (accept) 一个客户端的连接,这会创建一个新的套接字用于与该客户端通信。
    • 通过这个新套接字与客户端交换数据 (recv,send)。
    • 关闭套接字 (close)。
  2. 客户端 (Client):
    • 创建一个套接字 (socket)。
    • 连接到服务器的 IP 地址和端口 (connect)。
    • 通过套接字与服务器交换数据 (send,recv)。
    • 关闭套接字 (close)。

注意事项:

  • 本示例使用localhost(127.0.0.1) 作为通信地址,适合在本机上测试。
  • 代码中包含了基本的错误检查。
  • 服务器在处理完一个客户端后会退出。若要处理多个客户端,服务器需要在accept后创建新线程或进程。
  • 编译时需要链接网络库(在 Linux/macOS 上通常不需要特殊标志,但在 Windows 上需要链接ws2_32库)。

服务器代码 (server.c)

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h> // For close(), read(), write()

#include <sys/socket.h> // For socket functions

#include <netinet/in.h> // For sockaddr_in

#include <arpa/inet.h> // For inet_addr

#define PORT 8080

#define BUFFER_SIZE 1024

int main() {

int server_fd, new_socket;

struct sockaddr_in address;

int opt = 1;

int addrlen = sizeof(address);

char buffer[BUFFER_SIZE] = {0};

const char *hello = "Hello from server";

// 1. 创建服务器套接字

if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {

perror("socket failed");

exit(EXIT_FAILURE);

}

// 2. 设置套接字选项 (可选,例如允许地址重用)

if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,

&opt, sizeof(opt))) {

perror("setsockopt");

exit(EXIT_FAILURE);

}

// 3. 定义服务器地址结构

address.sin_family = AF_INET;

address.sin_addr.s_addr = inet_addr("127.0.0.1"); // 监听本地地址

address.sin_port = htons(PORT); // 监听端口

// 4. 将套接字绑定到地址

if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {

perror("bind failed");

exit(EXIT_FAILURE);

}

// 5. 开始监听

if (listen(server_fd, 3) < 0) {

perror("listen");

exit(EXIT_FAILURE);

}

printf("Server listening on port %d...\n", PORT);

// 6. 接受客户端连接

if ((new_socket = accept(server_fd, (struct sockaddr *)&address,

(socklen_t*)&addrlen)) < 0) {

perror("accept");

exit(EXIT_FAILURE);

}

printf("Client connected.\n");

// 7. 与客户端通信

int valread = read(new_socket, buffer, BUFFER_SIZE);

if (valread > 0) {

printf("Client said: %s\n", buffer);

}

send(new_socket, hello, strlen(hello), 0);

printf("Hello message sent to client\n");

// 8. 清理

close(new_socket);

close(server_fd);

return 0;

}

客户端代码 (client.c)

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h> // For close(), read(), write()

#include <sys/socket.h> // For socket functions

#include <netinet/in.h> // For sockaddr_in

#include <arpa/inet.h> // For inet_addr

#define PORT 8080

#define IP "127.0.0.1" // 服务器IP地址

#define BUFFER_SIZE 1024

int main() {

int sock = 0;

struct sockaddr_in serv_addr;

char *hello = "Hello from client";

char buffer[BUFFER_SIZE] = {0};

// 1. 创建客户端套接字

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);

// 2. 将 IP 地址从字符串转换为网络字节序

if(inet_pton(AF_INET, IP, &serv_addr.sin_addr)<=0) {

printf("\nInvalid address/ Address not supported \n");

return -1;

}

// 3. 连接到服务器

if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {

printf("\nConnection Failed \n");

return -1;

}

printf("Connected to server.\n");

// 4. 与服务器通信

send(sock, hello, strlen(hello), 0);

printf("Hello message sent to server\n");

int valread = read(sock, buffer, BUFFER_SIZE);

if (valread > 0) {

printf("Server said: %s\n", buffer);

}

// 5. 清理

close(sock);

return 0;

}

编译和运行

  1. 编译:

gcc -o server server.c

gcc -o client client.c

  1. 运行:
    • 首先,在一个终端窗口中启动服务器:./server

你会看到 "Server listening on port 8080..." 的提示。

    • 然后,在另一个终端窗口中运行客户端:./client
    • 回到服务器窗口,你应该能看到 "Client connected." 和 "Client said: Hello from client"。
    • 回到客户端窗口,你应该能看到 "Connected to server." 和 "Server said: Hello from server"。

这样,手写的 C 语言服务器和客户端就成功连接并交换了消息。

相关推荐
羽沢3110 分钟前
ECharts 学习
前端·学习·echarts
风行男孩12 分钟前
stm32基础学习——OLED显示屏的基本使用
stm32·嵌入式硬件·学习
一声沧海笑41 分钟前
【GEE学习笔记】GEE中如何上传矢量图?
笔记·学习
炽烈小老头1 小时前
【每天学习一点算法 2025/12/22】将有序数组转换为二叉搜索树
学习·算法
呱呱巨基1 小时前
Linux 进程控制
linux·c++·笔记·学习
暖阳之下1 小时前
学习周报二十七
学习
一念一花一世界2 小时前
sourcefare零基础学习 - 使用自定义权限优化项目管理
学习·sonarqube·sourcefare·代码扫描工具
代码游侠2 小时前
应用——MPlayer 媒体播放器系统代码详解
linux·运维·笔记·学习·算法
龘龍龙2 小时前
Python基础学习(六)
开发语言·python·学习
悠哉悠哉愿意2 小时前
【EDA学习笔记】电子技术基础知识:基本元件
笔记·嵌入式硬件·学习·eda