网络编程-tcp连接:服务器与客户端

使用服务器和客户端的代码,实现服务器和客户端的互相聊天功能
实现两台电脑之间互相聊天 

方案一:

服务器代码(server.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 8888
#define BUF_SIZE 1024// 客户端连接的套接字,供线程间共享
int client_sock = -1;// 线程函数:接收客户端消息并打印
void* recv_msg(void* arg) {char buf[BUF_SIZE];while (1) {// 读取客户端消息int len = read(client_sock, buf, sizeof(buf));if (len <= 0) {printf("客户端断开连接或接收失败\n");close(client_sock);pthread_exit(NULL); }buf[len] = '\0'; printf("客户端:%s\n", buf);}
}int main() {// 1. 创建监听套接字int server_sock = socket(AF_INET, SOCK_STREAM, 0);if (server_sock == -1) {perror("socket");return 1;}// 2. 绑定端口struct sockaddr_in server_addr;server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = INADDR_ANY;server_addr.sin_port = htons(PORT);if (bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {perror("bind");close(server_sock);return 1;}// 3. 监听连接if (listen(server_sock, 5) == -1) {perror("listen");close(server_sock);return 1;}printf("服务器启动,等待客户端连接...\n");// 4. 接受客户端连接struct sockaddr_in client_addr;socklen_t client_addr_len = sizeof(client_addr);client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &client_addr_len);if (client_sock == -1) {perror("accept");close(server_sock);return 1;}printf("客户端 %s:%d 已连接\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));// 5. 创建线程:专门处理接收客户端消息pthread_t recv_thread;if (pthread_create(&recv_thread, NULL, recv_msg, NULL) != 0) {perror("pthread_create");close(client_sock);close(server_sock);return 1;}// 分离线程,避免主线程调用 pthread_joinpthread_detach(recv_thread);// 6. 主线程:发送消息给客户端(从键盘输入)char buf[BUF_SIZE];while (1) {// 从键盘读取输入fgets(buf, sizeof(buf), stdin);// 去掉换行符(fgets 会把换行也读进来)buf[strcspn(buf, "\n")] = '\0'; // 发送给客户端write(client_sock, buf, strlen(buf)); }// 7. 关闭套接字(实际因 while(1) 很少走到这,可在信号或退出逻辑里处理)close(client_sock);close(server_sock);return 0;
}

客户端代码(client.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define SERVER_IP "127.0.0.1"  
#define PORT 8888             
#define BUF_SIZE 1024// 与服务器通信的套接字,供线程间共享
int sock = -1;// 线程函数:接收服务器消息并打印
void* recv_msg(void* arg) {char buf[BUF_SIZE];while (1) {// 读取服务器消息int len = read(sock, buf, sizeof(buf));if (len <= 0) {printf("服务器断开连接或接收失败\n");close(sock);pthread_exit(NULL); }buf[len] = '\0'; printf("服务器:%s\n", buf);}
}int main() {// 1. 创建套接字sock = socket(AF_INET, SOCK_STREAM, 0);if (sock == -1) {perror("socket");return 1;}// 2. 连接服务器struct sockaddr_in server_addr;server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);server_addr.sin_port = htons(PORT);if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {perror("connect");close(sock);return 1;}printf("已连接服务器 %s:%d\n", SERVER_IP, PORT);// 3. 创建线程:专门处理接收服务器消息pthread_t recv_thread;if (pthread_create(&recv_thread, NULL, recv_msg, NULL) != 0) {perror("pthread_create");close(sock);return 1;}// 分离线程pthread_detach(recv_thread);// 4. 主线程:发送消息给服务器(从键盘输入)char buf[BUF_SIZE];while (1) {// 从键盘读取输入fgets(buf, sizeof(buf), stdin);// 去掉换行符buf[strcspn(buf, "\n")] = '\0'; // 发送给服务器write(sock, buf, strlen(buf)); }// 5. 关闭套接字(实际很少走到,可在退出逻辑处理)close(sock);return 0;
}

方案二:

chat_client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>#define PORT 8888
#define BUFFER_SIZE 1024
#define SERVER_IP "127.0.0.1"int client_socket;
pthread_t send_thread, recv_thread;// 接收消息线程函数
void* receive_messages(void* arg) {char buffer[BUFFER_SIZE];while (1) {memset(buffer, 0, BUFFER_SIZE);int bytes_received = recv(client_socket, buffer, BUFFER_SIZE, 0);if (bytes_received <= 0) {printf("服务器断开连接\n");close(client_socket);exit(EXIT_SUCCESS);}printf("服务器: %s\n", buffer);}return NULL;
}// 发送消息线程函数
void* send_messages(void* arg) {char buffer[BUFFER_SIZE];while (1) {memset(buffer, 0, BUFFER_SIZE);fgets(buffer, BUFFER_SIZE, stdin);// 去除换行符size_t len = strlen(buffer);if (len > 0 && buffer[len-1] == '\n') {buffer[len-1] = '\0';}// 发送消息if (send(client_socket, buffer, strlen(buffer), 0) == -1) {perror("发送消息失败");close(client_socket);exit(EXIT_FAILURE);}// 输入"exit"退出聊天if (strcmp(buffer, "exit") == 0) {printf("退出聊天\n");close(client_socket);exit(EXIT_SUCCESS);}}return NULL;
}int main() {struct sockaddr_in server_addr;// 创建套接字client_socket = socket(AF_INET, SOCK_STREAM, 0);if (client_socket == -1) {perror("创建套接字失败");exit(EXIT_FAILURE);}// 准备服务器地址memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);server_addr.sin_port = htons(PORT);// 连接服务器if (connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {perror("连接服务器失败");exit(EXIT_FAILURE);}printf("已连接到服务器\n");printf("开始聊天,输入'exit'退出\n");// 创建发送和接收线程if (pthread_create(&send_thread, NULL, send_messages, NULL) != 0) {perror("创建发送线程失败");exit(EXIT_FAILURE);}if (pthread_create(&recv_thread, NULL, receive_messages, NULL) != 0) {perror("创建接收线程失败");exit(EXIT_FAILURE);}// 等待线程结束pthread_join(send_thread, NULL);pthread_join(recv_thread, NULL);// 关闭套接字close(client_socket);return 0;
}    

chat_server.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>#define PORT 8888
#define BUFFER_SIZE 1024int client_socket;
pthread_t send_thread, recv_thread;// 接收消息线程函数
void* receive_messages(void* arg) {char buffer[BUFFER_SIZE];while (1) {memset(buffer, 0, BUFFER_SIZE);int bytes_received = recv(client_socket, buffer, BUFFER_SIZE, 0);if (bytes_received <= 0) {printf("客户端断开连接\n");close(client_socket);exit(EXIT_SUCCESS);}printf("客户端: %s\n", buffer);}return NULL;
}// 发送消息线程函数
void* send_messages(void* arg) {char buffer[BUFFER_SIZE];while (1) {memset(buffer, 0, BUFFER_SIZE);fgets(buffer, BUFFER_SIZE, stdin);// 去除换行符size_t len = strlen(buffer);if (len > 0 && buffer[len-1] == '\n') {buffer[len-1] = '\0';}// 发送消息if (send(client_socket, buffer, strlen(buffer), 0) == -1) {perror("发送消息失败");close(client_socket);exit(EXIT_FAILURE);}// 输入"exit"退出聊天if (strcmp(buffer, "exit") == 0) {printf("退出聊天\n");close(client_socket);exit(EXIT_SUCCESS);}}return NULL;
}int main() {int server_socket;struct sockaddr_in server_addr, client_addr;socklen_t client_addr_len = sizeof(client_addr);// 创建套接字server_socket = socket(AF_INET, SOCK_STREAM, 0);if (server_socket == -1) {perror("创建套接字失败");exit(EXIT_FAILURE);}// 设置套接字选项int opt = 1;if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) {perror("设置套接字选项失败");exit(EXIT_FAILURE);}// 准备服务器地址memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = INADDR_ANY;server_addr.sin_port = htons(PORT);// 绑定套接字if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {perror("绑定套接字失败");exit(EXIT_FAILURE);}// 监听连接if (listen(server_socket, 1) == -1) {perror("监听失败");exit(EXIT_FAILURE);}printf("服务器已启动,等待客户端连接...\n");// 接受客户端连接client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &client_addr_len);if (client_socket == -1) {perror("接受连接失败");exit(EXIT_FAILURE);}printf("客户端已连接\n");printf("开始聊天,输入'exit'退出\n");// 创建发送和接收线程if (pthread_create(&send_thread, NULL, send_messages, NULL) != 0) {perror("创建发送线程失败");exit(EXIT_FAILURE);}if (pthread_create(&recv_thread, NULL, receive_messages, NULL) != 0) {perror("创建接收线程失败");exit(EXIT_FAILURE);}// 等待线程结束pthread_join(send_thread, NULL);pthread_join(recv_thread, NULL);// 关闭套接字close(client_socket);close(server_socket);return 0;
}    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/914615.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/914615.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

跨平台移动开发技术深度分析:uni-app、React Native与Flutter的迁移成本、性能、场景与前景

1. 引言 跨平台移动开发技术已成为提升开发效率、降低成本的战略性选择。uni-app、React Native&#xff08;RN&#xff09;和Flutter作为主流方案&#xff0c;在迁移成本、应用性能、适用场景及未来发展上呈现显著差异。本报告基于最新行业数据与技术演进&#xff08;2025年&…

详解低速容错CAN(附与高速CAN对比表)

文章目录前言一、低速容错CAN-低速二、低速容错CAN-容错2.1 信号电平2.2 终端电阻2.3 容错机制前言 在ISO 11898-3 Low-speed, fault-tolerant, medium-dependent interface部分描述了低速CAN的容错行为及其物理层内容。既然称为低速容错CAN&#xff0c;主要需要搞清楚的两个核…

维基框架发布 1.0.11 至中央仓,深化国产化 DevOps 生态整合

一、核心事件&#xff1a;维基框架 1.0.11 正式入驻中央仓库​ ​维基框架&#xff08;Wiki-Framework&#xff09;​​ 作为国产全场景 Java 企业级开发框架&#xff0c;于 7 月 9 日正式发布 ​v1.0.11 版本​ 至中央软件仓库&#xff08;Maven Central&#xff09;&#xf…

vscode 打开c++文件注释乱码

之前一直都主要用vscode编辑lua和python脚本语言&#xff0c;没怎么编辑过c文件&#xff0c;今天想打开一个文件看一个东西&#xff0c;但是注释全部乱码了&#xff0c;我也知道是文件编码的问题&#xff0c;但没找到修改编码格式的地方&#xff0c;好了废话不多说&#xff0c;…

波动回升正当时!期权合成多头:震荡市攻守兼备利器

上周&#xff0c;A股喜提关键突破&#xff01;上证指数自21年初以来首次稳稳站上3500点大关&#xff0c;市场整体震荡上行。尐程序&#xff1a;期权汇不过&#xff0c;热闹之下也藏有隐忧&#xff1a;虽然日均成交维持在1.4万亿加&#xff0c;但周五放量冲高&#xff08;成交达…

Python 基础(十四): 错误和异常

目录 1 错误2 异常 2.1 内置异常2.2 异常处理2.3 抛出异常2.4 自定义异常 程序中的错误我们通常称为 bug &#xff0c;工作中我们不仅需要改自己程序中的 bug &#xff0c;还需要改别人程序中的 bug &#xff0c;新项目有 bug 要改&#xff0c;老项目也有 bug 要改&#xff…

OpenCV-Python Tutorial : A Candy from Official Main Page(三)

3.11傅立叶变换3.11.1Fourier Transform in OpenCV-cv.dft、cv.magnitude、cv.idft这两个函数是图像频域处理&#xff08;如去噪、边缘增强、纹理分析&#xff09;的基础工具。1.cv.dft() —— 离散傅里叶变换功能&#xff1a; 将图像从空间域&#xff08;像素强度&#xff09;…

移动端字体适配

一、移动端图片适配1、使用 <img> 的 srcset<img src"logo.png"srcset"logo2x.png 2x,logo3x.png 3x"alt"Logo">优点&#xff1a;原生支持&#xff0c;浏览器自动选择最合适的图片。2、使用媒体查询切换背景图.logo {background-ima…

git起步

git官网&#xff1a;https://git-scm.com git使用手册&#xff1a;https://git-scm.com/book/zh/v2 一、Git 是什么&#xff1f; 1、版本控制 版本控制是一种记录一个或若干文件内容变化&#xff0c;以便将来查阅特定版本修订情况的系统。我们经常是用的是保存软件源代码的…

SSL与HTTP概述

一、概念1.SSL概念SSL&#xff08;Secure Sockets Layer&#xff09;是一种网络安全协议&#xff0c;用于在互联网通信中建立加密链接&#xff0c;保护在网络中传输的敏感数据免遭窃取或篡改。2.TLS概念虽然现在更先进的 TLS&#xff08;Transport Layer Security&#xff09; …

前端报错:“Uncaught SyntaxError: missing ) after argument list

问题描述&#xff1a;前端报错&#xff1a;“Uncaught SyntaxError: missing ) after argument list在 JavaScript 中遇到“SyntaxError: missing ) after argument list”这个错误通常意味着在函数调用或者声明中&#xff0c;参数列表的括号没有正确闭合。错误代码&#xff1a…

广州邮科光纤交换机的应用:网络世界中的幕后核心

你知道吗&#xff1f;在我们每天畅游互联网&#xff0c;发送邮件、看视频、打游戏时&#xff0c;背后支撑这一切流畅体验的关键设备之一就是光纤交换机。它像一个幕后英雄&#xff0c;默默地确保信息传输高效、稳定。那么&#xff0c;究竟邮科光纤交换机有哪些不可或缺的应用领…

C++内存布局、构造函数规则和优化策略解析

一、类对象内存布局深度解析 1.1 核心内存占用规则 ​非静态成员变量​&#xff1a;每个对象独立存储&#xff0c;按声明顺序排列&#xff08;含内存对齐填充&#xff09; 示例&#xff1a;class A{int x; char y;}; → 实际占用8字节&#xff08;413填充&#xff09;4​静态…

Fastapi框架总览与核心架构

Fastapi框架总览与核心架构 FastAPI 是一个基于 Python 的现代 Web 框架&#xff0c;专注于 高性能、高并发 和 开发效率&#xff0c;特别适合构建 异步 API 服务、微服务接口&#xff0c;同时在大模型接口封装中也广泛应用。它基于 Starlette&#xff08;异步 Web 框架&#x…

高并发四种IO模型的底层原理

高并发四种IO模型的底层原理 1 IO读写的基本原理 为了避免用户进程直接操作内核&#xff0c;保证内核安全&#xff0c;操作系统将内存&#xff08;虚拟内存&#xff09;划分为两部分&#xff1a;一部分是内核空间(Kernel-Space)&#xff0c;另一部分是用户空间(User-Space)。在…

腾讯云短信实战:Spring Boot接入YML配置与签名/模板/发送/统计/状态/号码包工具类详解

下面是一个Spring Boot集成腾讯云短信服务的详细示例&#xff0c;包含配置和6个工具类&#xff08;签名、模板、发送、统计、状态&#xff09;&#xff0c;采用YML配置&#xff1a; 1. 添加Maven依赖 <dependency><groupId>com.tencentcloudapi</groupId>&…

【Java篇】IntelliJ IDEA 安装与基础配置指南

序 本篇文章将介绍IDEA 2023 版本。 提高开发人员的生产力。无论您是刚开始接触编程的新手&#xff0c;还是经验丰富的开发专家。 一&#xff1a;官网下载安装包&#xff1a; IDEA下载链接 这个版本可以根据自己的需要选择。 二、安装方法 双击进这个.exe文件 这里要选择合…

2-Nodejs运行JS代码

2-Nodejs运行JS代码 创建一个 js 文件编写 JS 代码 要注意的是&#xff0c;在nodejs环境中不能操作浏览器 DOM 对象相关的api&#xff0c;在Nodejs 中运行 JS 代码 按住 shift 键&#xff0c;在 js 文件所在文件夹空白处右键&#xff0c;选择 Powershell 窗口执行如下命令&…

vue中使用西瓜播放器xgplayer (封装)+xgplayer-hls 播放.m3u8格式视频

1.西瓜播放器官网 http://h5player.bytedance.com/guide/2.安装 # 最新稳定版 $ npm install xgplayer对于已有项目也可以通过 CDN 引入&#xff0c;代码如下&#xff1a; <script src"//unpkg.byted-static.com/xgplayer/2.31.2/browser/index.js" type"tex…

2025-07-15通过边缘线检测图像里的主体有没有出血

本节观点&#xff1a;一个好的提问就已经解决了问题的90%。 对于问题的描述正确与否决定了解决问题的方法和路径&#xff0c;所以我们在AI时代必须要学会正确的描述问题和表达问题&#xff0c;否则即使有AI辅助也是很难精准的解决问题。 我的问题&#xff1a; 如何利用代码从图…