手把手教你搭建 UDP 多人聊天室(附完整源碼)

一、項目介紹???????

????????本文將分享一個基于 UDP 協議的簡易多人聊天室項目,包含服務器端和客戶端的完整實現。該聊天室支持多客戶端同時連接,能實現消息群發、用戶加入 / 退出通知等核心功能,適合作為網絡編程入門實踐案例。

????????項目采用 C 語言開發,利用 UDP 的無連接特性實現數據傳輸,通過鏈表管理在線客戶端信息,核心功能包括:

  • 服務器端:客戶端連接管理、消息轉發、加入 / 退出通知
  • 客戶端:消息發送、實時接收、退出控制
二、核心技術點
  1. UDP 協議應用
    采用SOCK_DGRAM類型的套接字實現無連接通信,通過sendtorecvfrom函數完成數據收發,無需建立持久連接,適合簡單的即時通訊場景。

  2. 鏈表數據結構
    服務器端使用鏈表存儲在線客戶端的 IP 和端口信息,實現客戶端的動態加入 / 刪除管理,通過遍歷鏈表完成消息群發(排除發送者自身)。

  3. 多線程編程
    客戶端采用主線程發送消息、子線程接收消息的設計,實現消息收發的并行處理,避免阻塞。

  4. 網絡字節序轉換
    使用htons/ntohsinet_addr/inet_ntoa等函數處理 IP 地址和端口的字節序轉換,保證跨平臺通信兼容性。

三、代碼解析
1. 服務器端(server.c)
  • 數據結構設計:定義liu結構體存儲客戶端地址信息,通過鏈表頭節點管理所有在線客戶端

  • 核心功能函數

    • qunfa:遍歷鏈表群發消息(排除發送者)
    • chuangjianlianbiao:新增客戶端到鏈表并廣播加入通知
    • panduan:判斷客戶端是否已在線
    • tuichu:處理客戶端退出,從鏈表移除并廣播退出通知
  • 主邏輯:循環接收客戶端消息,根據消息類型(普通消息 / 退出指令)和客戶端狀態(新用戶 / 老用戶)執行對應操作。

#include<myhead.h>
#define IP "192.168.175.46"
#define PORT 1111
typedef struct liu 
{struct sockaddr_in addr;struct liu *next;
} xue, *pxue;
pxue toujiedian() 
{pxue p = malloc(sizeof(xue));p->next = NULL;return p;
}
void qunfa(int oldfd,pxue L,char buff[],int n,struct sockaddr_in sender)//群發消息(不發給自己)
{pxue t = L->next;while(t) {if(!(t->addr.sin_addr.s_addr==sender.sin_addr.s_addr&&t->addr.sin_port==sender.sin_port))//不發給自己{sendto(oldfd,buff,n,0,(struct sockaddr*)&(t->addr),sizeof(struct sockaddr_in));}t = t->next;}
}
void chuangjianlianbiao(int oldfd,pxue L,struct sockaddr_in client) // 添加客戶端到鏈表并廣播加入消息
{pxue p = malloc(sizeof(xue));p->addr = client;p->next = L->next;L->next = p;char str[1024];sprintf(str,"系統消息:%s:%d 加入聊天室......",inet_ntoa(client.sin_addr),ntohs(client.sin_port));int n = strlen(str);qunfa(oldfd,L,str,n,client);//調用群發函數發送新用戶加入聊天室的信息
}
int panduan(pxue L, struct sockaddr_in client)// 判斷客戶端是否已存在
{pxue t=L->next;while(t)//t只要不是NULL就運行{if(t->addr.sin_addr.s_addr==client.sin_addr.s_addr&&t->addr.sin_port==client.sin_port) {return 0;// 已存在}t=t->next;}return 1;// 不存在
}
void tuichu(int oldfd,pxue L,struct sockaddr_in client)// 客戶端退出處理 
{pxue t = L->next;pxue Q = L;while(t) {if(t->addr.sin_addr.s_addr==client.sin_addr.s_addr&&t->addr.sin_port==client.sin_port) {         char str[1024];sprintf(str,"系統消息:%s:%d 退出了聊天室......",inet_ntoa(client.sin_addr),ntohs(client.sin_port));int n = strlen(str);qunfa(oldfd,L,str,n,client);//群發退出消息  Q->next = t->next;free(t);//從鏈表刪除return;}Q = t;t = t->next;}
}
int main(int argc,const char*argv[]) 
{int oldfd=socket(AF_INET, SOCK_DGRAM, 0);if(oldfd==-1) {perror("socket");return -1;}struct sockaddr_in server={.sin_family=AF_INET,.sin_port=htons(PORT),.sin_addr.s_addr=inet_addr(IP)};if(bind(oldfd,(struct sockaddr*)&server,sizeof(server))==-1) {perror("bind");return -1;}pxue L=toujiedian();char buff[1024];struct sockaddr_in client;int len = sizeof(client);printf("UDP聊天室服務器已啟動,等待客戶端連接...\n");while(1) {bzero(buff,sizeof(buff));int n=recvfrom(oldfd,buff,sizeof(buff),0,(struct sockaddr*)&client, &len);//有新客戶端連接或者有舊客戶端發消息會觸發if(n<0) {perror("recvfrom");continue;}buff[n] = '\0';if(strcmp(buff,"quit")==0)//先判斷消息是否為退出指令,不進入新老客戶判斷{tuichu(oldfd,L,client);//如果是退出指令,直接進入退出處理函數continue;}if(panduan(L,client))//確定不是退出指令后,判斷發信息的客戶端是否存儲在鏈表里{chuangjianlianbiao(oldfd, L, client);//不存在就創建并存儲客戶端信息,同時廣播加入信息}char str[1024];bzero(str,sizeof(str));sprintf(str,"%s:%d發來:",inet_ntoa(client.sin_addr),ntohs(client.sin_port));strcat(str,buff);qunfa(oldfd,L,str,n,client);//存在就群發客戶端發來的消息}close(oldfd);return 0;
}
2. 客戶端(客戶端 1.c)
  • 多線程設計:子線程jieshou循環接收服務器轉發的消息并打印,主線程負責讀取用戶輸入并發送。
  • 通信流程:綁定本地地址后連接服務器,輸入消息自動發送,輸入 "quit" 時退出聊天室并通知服務器。
#include<myhead.h>
#define IP "192.168.175.46"// 服務端IP
#define PORT 1111// 服務端端口
int oldfd;
void *jieshou()// 接收線程
{char buff[1024];struct sockaddr_in from;int len = sizeof(from);while(1) {bzero(buff, sizeof(buff));int n =recvfrom(oldfd,buff,sizeof(buff),0,(struct sockaddr*)&from,&len);if(n>0) {buff[n]='\0';printf("%s\n",buff);}}
}
int main(int argc,const char*argv[]) 
{oldfd= socket(AF_INET,SOCK_DGRAM, 0);if(oldfd == -1) {perror("socket");return -1;}//綁定客戶端自己的地址struct sockaddr_in client={.sin_family=AF_INET,.sin_port=htons(2222),.sin_addr.s_addr=inet_addr("192.168.175.46")};if(bind(oldfd,(struct sockaddr*)&client,sizeof(client))==-1) {perror("bind");return -1;}//要連接的服務器地址struct sockaddr_in server={.sin_family = AF_INET,.sin_port = htons(PORT),.sin_addr.s_addr = inet_addr(IP)};printf("\t\t連接到聊天室服務器 %s:%d\n",IP,PORT);printf("\t\t輸入消息并回車即可發送,輸入 quit 退出聊天室\n");// 創建接收線程pthread_t tid;pthread_create(&tid,NULL,jieshou,NULL);pthread_detach(tid);//告訴系統:這個線程結束后,幫我自動回收// 主線程負責發送char buff[1024];while(1) {bzero(buff, sizeof(buff));fgets(buff, sizeof(buff),stdin);buff[strlen(buff)-1] = '\0';sendto(oldfd,buff,sizeof(buff),0,(struct sockaddr*)&server,sizeof(server));if(strcmp(buff, "quit")==0) {printf("您已退出聊天室\n");break;}}close(oldfd);return 0;
}
四、運行效果
  1. 啟動服務器后,顯示 "UDP 聊天室服務器已啟動,等待客戶端連接..."
  2. 客戶端啟動后,自動連接服務器并加入聊天室,其他在線用戶會收到 "系統消息:IP: 端口 加入聊天室......"
  3. 任一客戶端發送消息,其他客戶端會收到 "IP: 端口發來:消息內容"
  4. 客戶端輸入 "quit",其他用戶會收到退出通知,該客戶端從在線列表中移除
五、總結與擴展方向

本項目實現了 UDP 聊天室的基礎功能,可進一步擴展:

  • 增加用戶昵稱功能(替代 IP: 端口顯示)
  • 實現私聊功能(指定接收者 IP 和端口)
  • 加入消息加密機制,提升安全性
  • 增加客戶端心跳檢測,處理異常斷開情況

完整代碼已附在文中,適合網絡編程初學者參考學習,如有問題歡迎留言交流。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/95353.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/95353.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/95353.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Vue基礎知識-使用監視屬性watch和計算屬性computed實現列表過濾+排序

一、完整源碼<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><script src…

自動化運維-ansible中的管理機密

自動化運維-ansible中的管理機密 一、Ansible Vault 在自動化配置管理中&#xff0c;直接以純文本形式存儲密碼、API密鑰、證書等敏感信息是極大的安全漏洞。Ansible Vault 正是為了解決這一問題而設計的核心功能 Ansible Vault 是 Ansible 的一個核心功能&#xff0c;它允許用…

UFUNCTION C++ 的再次理解

一.UFUNCTION 格式和屬性也比較像&#xff0c;兩部分 函數說明符&#xff0c;和元數據說明符UFUNCTION不僅能 控制對藍圖公開&#xff0c;還能與 綁定委托&#xff0c;用戶輸入,網絡回調功能相關聯&#xff0c;而且還能創建自己控制帶命令二.函數說明符控制 &#xff0c;函數在…

《論文閱讀》從心到詞:通過綜合比喻語言和語義上下文信號產生同理心反應 2025 ACL findings

《論文閱讀》從心到詞:通過綜合比喻語言和語義上下文信號產生同理心反應 2025 ACL findings 前言 創新點 形象語言 (Figurative Language) 語義上下文信號(Semantic Context Signals) 模型架構 情緒原因標注 形象語言元數據獲取 共情回復生成 實驗結果 總結 趨勢 前言 親…

MySQL內置的各種單行函數

精選專欄鏈接 &#x1f517; MySQL技術筆記專欄Redis技術筆記專欄大模型搭建專欄Python學習筆記專欄深度學習算法專欄 歡迎訂閱&#xff0c;點贊&#xff0b;關注&#xff0c;每日精進1%&#xff0c;與百萬開發者共攀技術珠峰 更多內容持續更新中&#xff01;希望能給大家帶來…

Python OpenCV圖像處理與深度學習:Python OpenCV視頻處理入門

視頻處理基礎&#xff1a;掌握OpenCV視頻操作 學習目標 通過本課程&#xff0c;學員們將學習如何使用Python和OpenCV庫來處理視頻文件&#xff0c;包括讀取視頻、捕獲攝像頭視頻流、處理視頻幀以及保存處理后的視頻&#xff0c;同時&#xff0c;能夠獨立完成基本的視頻處理任務…

AI 賦能 Java 開發效率:全流程痛點解決與實踐案例(四)

文檔與注釋自動化&#xff1a;從 “手動撰寫” 到 “實時同步”&#xff0c;降低維護成本 &#x1f4c4; Java 開發強調 “文檔先行”&#xff0c;Javadoc 注釋、架構文檔、接口文檔是項目維護的重要資產。但手動撰寫文檔存在兩大痛點&#xff1a;一是耗時&#xff08;開發者平…

【機器學習學習筆記】pandas基礎

零基礎入門 Pandas&#xff1a;數據處理的 "萬能工具"如果你是剛接觸數據分析的小白&#xff0c;一定聽過 "Pandas" 這個名字。簡單說&#xff0c;Pandas 是 Python 中專門用來處理數據的工具庫&#xff0c;就像 Excel 的 "高級版"—— 能更快、…

(Mysql)MVCC、Redo Log 與 Undo Log

1. MVCC&#xff08;多版本并發控制&#xff09;概念 MVCC&#xff08;Multi-Version Concurrency Control&#xff09;是一種數據庫并發控制機制&#xff0c;用于解決 讀寫沖突&#xff0c;提高數據庫并發性能。MySQL InnoDB 存儲引擎使用 MVCC 來實現 非阻塞讀&#xff08;即…

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

4.5FAST Algorithm for Corner Detection 4.5.1FAST算法 我們已了解多種特征檢測器&#xff0c;其中許多效果出色。但從實時應用的角度來看&#xff0c;它們的速度仍不夠快。一個典型例子是計算資源有限的SLAM&#xff08;同步定位與建圖&#xff09;移動機器人。 為解決此問…

LINUX 91 SHELL:刪除空文件夾 計數

問題 [rootweb ~]# find -type f -exec echo "file:{}" $path; find: 遺漏“-exec”的參數 您在 /var/spool/mail/root 中有郵件[rootweb ~]# $path/root -bash: /root: 沒有那個文件或目錄 您在 /var/spool/mail/root 中有新郵件 [rootweb ~]# path/root [rootweb ~…

視頻軟解碼技術詳解:原理、應用與未來發展

視頻軟解碼的基本原理 概念解析&#xff1a;CPU主導的通用解碼方式 視頻軟解碼是一種完全依賴通用CPU執行解碼算法的視頻還原技術&#xff0c;其核心特征在于不依賴任何專用硬件模塊&#xff0c;而是通過軟件程序調用CPU的通用計算能力完成壓縮視頻數據的解碼過程[1][2]。與硬…

線性回歸中梯度下降與正規方程以及擬合問題與正則化

線性回歸實戰指南&#xff1a;從理論到實踐 目錄 線性回歸理論基礎機器學習項目開發流程波士頓房價預測實戰梯度下降與正規方程模型評估指標擬合問題與正則化總結與展望 1. 線性回歸理論基礎 1.1 什么是線性回歸&#xff1f; 線性回歸是一種監督學習算法&#xff0c;用于預…

為什么46.1k程序員都在用這個AI繪畫神器?我體驗一周后終于明白了

大家好&#xff0c;我是顧北&#xff0c;一名AI應用探索者&#xff0c;也是GitHub開源項目收集者。說起AI繪畫這事兒&#xff0c;我之前真的是又愛又恨。上個月想給朋友搞張生日賀圖&#xff0c;結果在Stable Diffusion WebUI里折騰了大半天。采樣步數&#xff1f;CFG比例&…

Java基礎第8天總結(map遍歷、Stream流)

選中一部分代碼&#xff0c;然后CTRLALTT&#xff0c;可以在外面套上while循環,try..catch之類的小案例&#xff1a;電影信息管理模塊&#xff1a;用戶可以上架、查詢、下架、下架某個主演參演的電影package Demo;import lombok.AllArgsConstructor; import lombok.Data; impor…

總線矩陣的原理

總線矩陣&#xff08;Bus Matrix&#xff09;是多主設備共享多從設備的智能連接與仲裁核心&#xff0c;本質是一個“靈活的交叉開關陣列”&#xff0c;用于解決多個主設備&#xff08;如CPU、DMA、GPU&#xff09;同時訪問多個從設備&#xff08;如內存、外設、存儲芯片&#x…

硬件開發_基于Zigee組網的果園養殖監控系統

一.系統概述 果園環境監控系統功能如下&#xff1a; 核心控制器&#xff1a;以STM32為核心控制器&#xff0c;承擔整體的數據采集、處理及控制任務。環境參數監測&#xff1a;集成溫度傳感器、CO?傳感器、光照傳感器和土壤濕度傳感器&#xff0c;可實時采集果園內的溫度、二氧…

K8s調度核心:從Pod分配到節點優化

在 Kubernetes&#xff08;K8s&#xff09;中&#xff0c;Pod 調度是指 K8s 系統根據特定規則和策略&#xff0c;將 Pod 合理分配到集群中的某個節點&#xff08;Node&#xff09;上運行的過程。其核心目標是確保 Pod 在合適的節點上高效、穩定地運行&#xff0c;充分利用集群資…

Tomcat 企業級運維實戰系列(四):Tomcat 企業級監控

Tomcat 企業級運維實戰系列&#xff08;四&#xff09;&#xff1a;Tomcat 企業級監控一&#xff1a;監控工具1&#xff09;概述2&#xff09;流程3&#xff09;部署二&#xff1a;監控命令1&#xff09;jps2&#xff09;jstack3&#xff09;jmap4&#xff09;MAT 工具分析三&a…

技術干貨丨HyperMesh 新界面功能與技術升級解析

全文內容選自 Altair 區域技術交流會華東站Altair 高級技術經理 張晨《HyperWorks 2025&#xff1a;下一代建模可視化和二次開發平臺》演講1、引言今天我為大家介紹 HyperMesh——這個大家既熟悉又陌生的工具。說熟悉&#xff0c;是因為它一直是工程仿真領域的主流建模軟件&…