手写服务器与手写客户端相连接-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 语言服务器和客户端就成功连接并交换了消息。

相关推荐
Alice-YUE40 分钟前
【js高频八股】防抖与节流
开发语言·前端·javascript·笔记·学习·ecmascript
北山有鸟2 小时前
修改源码法和插件法
嵌入式硬件·学习
richxu202510012 小时前
嵌入式学习之路->stm32篇->(14)通用定时器(上)
stm32·单片机·嵌入式硬件·学习
qeen872 小时前
【数据结构】建堆的时间复杂度讨论与TOP-K问题
c语言·数据结构·c++·学习·
lizhihai_993 小时前
股市学习心得-六张分时保命图
大数据·人工智能·学习
nashane3 小时前
HarmonyOS 6学习:应用签名文件丢失处理与更新完全指南
学习·华为·harmonyos·harmonyos 5
@codercjw3 小时前
公差的具体标注方法(书本上/理论上标注方法)
学习
久菜盒子工作室4 小时前
时寒冰:第五次产业大转移与未来30年国运:在“双向挤压”中实现惊险一跃
人工智能·学习
Amazing_Cacao5 小时前
CFCA精品可可产区认证课程风土解析(美洲):打破风味堆叠的假象,建立时间轴上的层次展开阅读系统
学习
永远不会的CC5 小时前
浙江华昱欣实习(4月23日~ 4月19日)
后端·学习