網絡編程-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
英文地址,請注明出處:http://en.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; 如何利用代碼從圖…