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

相关推荐
nashane9 小时前
HarmonyOS 6学习:JsCrash“闪退”法医指南——从FaultLog堆栈还原崩溃现场的终极手册
学习·华为·harmonyos
for_ever_love__9 小时前
UI学习:UICollectionView瀑布流
学习·ui·ios·objective-c·cocoa
AOwhisky9 小时前
MySQL 学习笔记(第六期):MySQL 备份与恢复
运维·数据库·笔记·学习·mysql·云计算
_李小白10 小时前
【android opencv学习笔记】Day 32:直线检测之霍夫变换
android·opencv·学习
提子拌饭13311 小时前
Column 嵌套布局:多级 Column 实现复杂纵向结构——鸿蒙 HarmonyOS ArkTS 原生学习应用
学习·华为·harmonyos·鸿蒙·鸿蒙系统
xqqxqxxq12 小时前
树结构技术学习笔记
数据结构·笔记·学习
十月的皮皮13 小时前
C语言学习笔记202606008- 三角形判断(3种方法)
c语言·笔记·学习
XGeFei13 小时前
【Fastapi学习笔记(6)】—— Fastapi文件上传、请求头自动转换
笔记·学习·fastapi
一口吃俩胖子13 小时前
【脉宽调制DCDC功率变换学习笔记024】频域性能
笔记·学习
吃着火锅x唱着歌13 小时前
深度探索C++对象模型 学习笔记 第五章 构造、解构、拷贝语意学(2)
c++·笔记·学习