基於linux的TCP網路聊天室設計與實現
利用Linux實現基於TCP模式的網路聊天程式
主要完成的兩大組成部分為:伺服器和客戶端。
- 伺服器程式主要負責監聽客戶端發來的訊息。
- 客戶端需要登入到伺服器端才可以實現正常的聊天功能。該程式是利用程序以及共享記憶體來實現群傳送訊息的。
以下簡單分析一下伺服器端和客戶端兩個方面所要完成的任務。
伺服器的主要功能如下:
- 在特定的埠上進行監聽,等待客戶端的連線。
- 使用者可以配置伺服器端的監聽埠。
- 向連線的客戶端傳送登入成功資訊。
- 向已經連線到伺服器的客戶端的使用者傳送系統訊息。
- 使用TCP多執行緒併發伺服器,向線上的所有客戶端傳送訊息
客戶端的主要功能如下:
- 客戶端傳參輸入IP和埠號以及使用者名稱進行註冊
- 連線到已經開啟的服務的服務端
- 使用者可以向所有人傳送資訊
- 使用者可以接受伺服器傳送的系統訊息
伺服器功能描述
伺服器主要是負責監聽客戶端傳送來的訊息,利用TCP執行緒併發伺服器模型實現對客戶端的監聽接收。
伺服器程式的作用為:初始化伺服器程式,持續監聽一個固定的埠,收到客戶的連線後建立一個socket連線,與客戶進行通訊和資訊處理,接收客戶通過socket連線傳送來的資料,建立一個新的socket;通過socket連線與客戶通訊,進行響應處理,並返回結果,通訊結束後終端與客戶的連線(關閉socket);主要的過程為伺服器建立一個共享記憶體空間函式,以及客戶端簡單的介面,利用套接字模型機制實現伺服器簡易模型的實現,利用 socket()建立流式套接字,並可以返回套接自號;利用bind()實現套接字與本地地址相連,listen()通知TCP伺服器準備好監聽客戶端的連線,accept()接收連線,等待客戶端的連線,建立連線之後accept返回新的標識客戶端的套接字,運用多執行緒以及recv()/send()接收發送資料;客戶端功能描述
客戶端主要用來向伺服器端傳送資料,客戶端程式的作用:初始化客戶程式,連線到某個伺服器上,建立socket連線,通過socket連線向伺服器傳送請求資訊,通訊結束後中斷與客戶的連線。主要的實現步驟為:需要定義執行時候需要的引數,同樣利用socket()建立流式套接字,返回套接字號,connect()將套接字與遠端主機連線,recv()和send()將套接字上的讀寫資料進行傳送與接收,close()關閉套接字,關閉對話。
c.c
#include<stdio.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/types.h> #include<string.h>
#include<stdlib.h>
#include<netdb.h>
#include<unistd.h>
#include<signal.h>
#include<errno.h>
#include<time.h>
#define SIZE 1024
int main(int argc, char *argv[])
{
pid_t pid;
int sockfd,confd;
char buffer[SIZE],buf[SIZE];
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
struct hostent *host;
short port;
char *name;
//四個引數
if(argc!=4)
{
fprintf(stderr,"Usage:%s hostname \a\n",argv[0]);
exit(1);
}
//使用hostname查詢host 名字
if((host=gethostbyname(argv[1]))==NULL)
{
fprintf(stderr,"Gethostname error\n");
exit(1);
}
port=atoi(argv[2]);
name=argv[3];
/*客戶程式開始建立 sockfd描述符 */
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));
exit(1);
} else{
printf("Socket successful!\n");
}
/*客戶程式填充服務端的資料 */
bzero(&server_addr,sizeof(server_addr)); // 初始化,置0
server_addr.sin_family=AF_INET; // IPV4
server_addr.sin_port=htons(port); // (將本機器上的short資料轉化為網路上的short資料)埠號
server_addr.sin_addr=*((struct in_addr *)host->h_addr); // IP地址
/* 客戶程式發起連線請求 */
if(confd=connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));
exit(1);
}else{
printf("Connect successful!\n");
}
/*將客戶端的名字傳送到伺服器端*/
send(sockfd,name,20,0);
/*建立子程序,進行讀寫操作*/
pid = fork();//建立子程序
while(1)
{
/*父程序用於傳送資訊*/
if(pid > 0)
{
/*時間函式*/
struct tm *p;
time(&timep);
p = localtime(&timep);
strftime(buffer, sizeof(buffer), "%Y/%m/%d %H:%M:%S", p);
/*輸出時間和客戶端的名字*/
strcat(buffer," \n\t暱稱 ->");
strcat(buffer,name);
strcat(buffer,":\n\t\t ");
memset(buf,0,SIZE);
fgets(buf,SIZE,stdin);
/*對客戶端程式進行管理*/
if(strncmp("e",buf,1)==0)
{
printf("該客戶端下線...\n");
strcat(buffer,"退出聊天室!");
if((send(sockfd,buffer,SIZE,0)) <= 0)
{
perror("error send");
}
close(sockfd);
sockfd = -1;
exit(0);
}else
{
strncat(buffer,buf,strlen(buf)-1);
strcat(buffer,"\n");
if((send(sockfd,buffer,SIZE,0)) <= 0)
{
perror("send");
}
}
}
else if(pid == 0)
{
/*子程序用於接收資訊*/
memset(buffer,0,SIZE);
if(sockfd > 0)
{
if((recv(sockfd,buffer,SIZE,0)) <= 0)
{
close(sockfd);
exit(1);
}
printf("%s\n",buffer);
}
}
} close(sockfd);
return 0;
}
s.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<string.h>
#include<unistd.h>
#include<signal.h>
#include<sys/ipc.h>
#include<errno.h>
#include<sys/shm.h>
#include<time.h>
#include<pthread.h>
#define PORT 4395
#define SIZE 1024
#define SIZE_SHMADD 2048
#define BACKLOG 3
int sockfd;
int fd[BACKLOG];
int i=0;
/*********套接字描述符*******/
int get_sockfd()
{ struct sockaddr_in server_addr; if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) { fprintf(stderr,"Socket error:%s\n\a",strerror(errno)); exit(1); }else{
printf("Socket successful!\n"); } /*sockaddr結構 */
bzero(&server_addr,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(PORT);
/*繫結伺服器的ip和伺服器埠號*/
if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{ fprintf(stderr,"Bind error:%s\n\a",strerror(errno));
exit(1);
} else{printf("Bind successful!\n"); }
/* 設定允許連線的最大客戶端數 */
if(listen(sockfd,BACKLOG)==-1)
{ fprintf(stderr,"Listen error:%s\n\a",strerror(errno)); exit(1); } else{
printf("Listening.....\n"); }
return sockfd;
}
/*建立共享儲存區*/
int shmid_create()
{ int shmid; if((shmid = shmget(IPC_PRIVATE,SIZE_SHMADD,0777)) < 0) { perror("shmid error!"); exit(1); }
Else printf("shmid success!\n");
return shmid;
}
int main(int argc, char *argv[]) { char shmadd_buffer[SIZE_SHMADD],buffer[SIZE]; struct sockaddr_in client_addr;
int sin_size;
pid_t ppid,pid; int new_fd;
int shmid;
char *shmadd;
/***********共享記憶體**************/
shmid = shmid_create();
//對映共享記憶體
shmadd = shmat(shmid, 0, 0);
/*****建立套接字描述符***********/
int sockfd = get_sockfd();
/*迴圈接收客戶端*/
while(1)
{ /* 伺服器阻塞,直到客戶程式建立連線 */
sin_size=sizeof(struct sockaddr_in);
if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1)
{ fprintf(stderr,"Accept error:%s\n\a",strerror(errno)); exit1); }else{printf("Accept successful!\n"); }
fd[i++] = new_fd;
printf("\n已連線了客戶端%d : %s:%d \n",i , inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
/*把介面傳送給客戶端*/
memset(buffer,0,SIZE);
strcpy(buffer,"\n——————————————————Welecom come char ———————————————————————\n");
send(new_fd,buffer,SIZE,0);
//建立子程序客戶端
ppid = fork(); if(ppid == 0)
{
//將加入的新客戶傳送給所有線上的客戶端/
recv(new_fd,buffer,SIZE,0);
strcat( buffer," 進入了聊天室....");
for(i=0;i<BACKLOG;i++)
{
if(fd[i]!=-1)
{
send(fd[i],buffer,strlen(buffer),0);
}
}
//建立子程序進行讀寫操作/
pid = fork();
while(1)
{
if(pid > 0)
{
//父程序用於接收資訊/
memset(buffer,0,SIZE);
if((recv(new_fd,buffer,SIZE,0)) <= 0)
{
close(new_fd);
exit(1); }
memset(shmadd, 0, SIZE_SHMADD);
strncpy(shmadd, buffer, SIZE_SHMADD);//將快取區的客戶端資訊放入共享記憶體裡
printf(" %s\n",buffer);
}
if(pid == 0)
{
//子程序用於傳送資訊/
sleep(1);//先執行父程序
if(strcmp(shmadd_buffer,shmadd) != 0)
{
strcpy(shmadd_buffer,shmadd);
if(new_fd > 0)
{
if(send(new_fd,shmadd,strlen(shmadd),0) == -1)
{
perror("send");
}
memset(shmadd, 0, SIZE_SHMADD);
strcpy(shmadd,shmadd_buffer);
}
}
}
}
}
} free(buffer);
close(new_fd);
close(sockfd);
return 0;
}
伺服器進行編譯執行
客戶端進行編譯執行
伺服器出現結果
另外開啟一個終端執行對客戶端程式碼編譯執行
相關推薦
基於linux的TCP網路聊天室設計與實現
利用Linux實現基於TCP模式的網路聊天程式 主要完成的兩大組成部分為:伺服器和客戶端。 伺服器程式主要負責監聽客戶端發來的訊息。 客戶端需要登入到伺服器端才可以實現正常的聊天功能。該程式是利用程序以及共享記憶體來實現群傳送訊息的。 以下簡單分析一下
基於Android簡單備忘錄的設計與實現(附git原始碼連結)
前言 課程作業需要,於是忙活兩天寫了一個簡單的備忘錄,使用了ListView,SQLite。 開發環境:Android Studio 原始碼連結:https://gitee.com/zg0212/Memoire 功能截圖 主頁面 新建頁面
[原始碼和文件分享]基於組合語言的音樂盒設計與實現
基於組合語言的音樂盒設計與實現—彙編課設 一 需求分析 設計一個音樂盒,可用在諸如生日禮品等場景裡。 包含的功能有播放音樂、切換音樂。預設播放第一首音樂,單曲迴圈。當撥動控制開關時切換歌曲,總共三首,分別由三個開關控制。當且僅當一個開關開啟其它開關關閉時有效,多個開關同時開啟時無效。
kubernetes容器網路介面(CNI) midonet網路外掛的設計與實現_Kubernetes中文社群
相關原理概述 先來講講什麼是CNI? CNI(容器網路介面)是一種操作容器網路規範,包含方法規範,引數規範等。 CNI只關心容器的網路連線,在容器建立時分配網路資源,並在刪除容器時刪除分配的資源。因為這個焦點,CNI有廣泛的支援,規格易於實現。CNI介面只需要實現兩個方法,一個建立容器時呼叫,一個刪除容器時
基於SpringCloud的微服務設計與實現
Spring Boot是在 2013年推出的新專案,主要用來簡化Spring 開發框架的開發、配置、除錯、部署工作,同時在專案內集成了大量易於使用且實用的基礎框架[[i]]。使用Spring Boot開發專案,可以做到一鍵啟動和部署,整個開發過程得到了很大的簡化。Sp
基於Java軟體開發平臺設計與實現溫溼度檢測系統
**基於Java軟體開發平臺設計與實現溫溼度檢測系統** 基於Java軟體開發平臺設計與實現溫溼度檢測系統mysql資料庫建立語句 基於Java軟體開發平臺設計與實現溫溼度檢測系統oracle資料庫建立語句 基於Java軟體開發平臺設計與實現溫溼度檢測系統sqlserve
java聊天室設計及實現
這是大二剛學java時做的東西,執行伺服器,註冊兩個客戶端,登入後客戶端之間可以進行文字聊天,有群發功能。 如何實現: 呼叫ServerSocket來建立繫結在指定埠上的伺服器,然後呼叫accept方法阻塞,等待客戶端的連線,連上後返回socket連線物件。 然後將
網路爬蟲框架設計與實現
引題 最近在看go語言的程式設計實現,裡面有這個專案,感覺不錯,在這裡簡 要總結和學習心得,給大家一個引路,如果想要具體瞭解可以看《GO 語言併發實踐》 專案介紹 網
[原始碼和文件分享]基於JAVA3D的網路三維技術的設計與實現
摘 要 網際網路的出現及飛速發展使IT業的各個領域發生了深刻的變化,它必然引發一些新技術的出現。3D圖形技術並不是一個新話題,在圖形工作站以至於PC機上早已日臻成熟,並已應用到各個領域。然而網際網路的出現,卻使3D圖形技術發生了和正在發生著微妙而深刻的變化。Web3D協會(前身是VRML協會)最
基於神經網路的目標檢測論文之目標檢測系統:實時路況檢測系統的設計與實現
注:本文源自本人的碩士畢業論文,未經許可,嚴禁轉載! 原文請參考知網:知網地址 第五章 實時路況檢測系統的設計與實現 物體識別技術被廣泛應用於人們的生產生活中。隨著深度學習與雲端計算的飛速發展,帶動了物體識別技術產生質的飛躍。高解析度影象和檢測的實時性要求越來越
基於ssm的影迷互動的網路平臺設計與實現
**基於ssm的影迷互動的網路平臺設計與實現** 基於ssm的影迷互動的網路平臺設計與實現mysql資料庫建立語句 基於ssm的影迷互動的網路平臺設計與實現oracle資料庫建立語句 基於ssm的影迷互動的網路平臺設計與實現sqlserver資料庫建立語句 基於ss
基於WEB的網路遠端作業處理系統之使用者介面的設計與實現,java設計與開發
**基於WEB的網路遠端作業處理系統之使用者介面的設計與實現,java設計與開發** 基於WEB的網路遠端作業處理系統之使用者介面的設計與實現mysql資料庫建立語句 基於WEB的網路遠端作業處理系統之使用者介面的設計與實現oracle資料庫建立語句 基於WEB的網路遠端
14 QT TCP網路程式設計與網路聊天室的實現
網路裝置:用於遠端的計算機間的通訊. 每個網路裝置都有一個ip地址. ip地址用於區分一個區域網內不同的計算機, ip地址在同一個區域網內不可以重複使用(如重複使用會兩個都連不了網), ip地址可由路由器動態分配,也可以手動指定. 網路掩碼用於指定所屬的區域
IM系統中聊天記錄模塊的設計與實現
人的 dex auto 由於 模型 速度 開發 構造 qlite 看到很多開發IM系統的朋友都想實現聊天記錄存儲和查詢這一不可或缺的功能,這裏我就把自己前段時間為傲瑞通(OrayTalk)開發聊天記錄模塊的經驗分享出來,供需要的朋友參考下。 一.總體設計 1.存儲位置
基於面部識別的日誌系統的設計與實現
history 教訓 並且 else -o 經驗 文件 self 線程 基於面部識別的日誌系統的設計與實現 @(GUI程序開發)[PyQt, 信號, 面部識別, 多線程, 媒體播放, opencv] [TOC] 需求與設計 使用面部識別技術,識別進出重要通道的人員,並對
課程設計小組報告——基於ARM實驗箱的捕魚遊戲的設計與實現
訓練 RR article 有一個 fish res 粒子 等級 遊戲流程 課程設計小組報告——基於ARM實驗箱的捕魚遊戲的設計與實現 一、任務簡介 1.1 任務內容 捕魚遊戲這個項目是一個娛樂性的遊戲開發,該遊戲可以給人們帶來娛樂的同時還可以給人感官上的享受,所以很受人們
課程設計個人報告——基於ARM實驗箱的捕魚遊戲的設計與實現
win 代碼 files 軟件 AR 準備 file JD ogr 課程設計個人報告——基於ARM實驗箱的捕魚遊戲的設計與實現 一、實驗環境 Eclipse軟件開發環境; ARM實驗箱(HonyaS5PC100); windows操作系統。 二、實踐內容 Window
20155338課程設計個人報告——基於ARM實驗箱的Android交友軟件的設計與實現
ive serve clip spl ogl help software 開拓 按鈕 課程設計個人報告——基於ARM實驗箱的Android交友軟件的設計與實現 個人貢獻 實驗環境的搭建 代碼調試 在電腦上成功運行 研究程序代碼撰寫小組報告 一、實驗環境 1、Eclips
基於SSM框架賀州學院校園二手交易平臺設計與實現
jstl 轉換 重要 ets 做了 esp receive list 密碼登錄 註:畢業有一段時間了,這裏了做一下當年畢設的經驗分享。 緒論 隨著中國新四大發明的誕生,網購成了千千萬萬網友們購物的新方式,新的購物方式促進商業的發展,但隨著人們生活水平的提高,許多新購
基於WebGIS的Web服務器日誌管理系統設計與實現_愛學術——免費下載
富客戶端 平臺 .com 服務器日誌 操作 shu 實現 c51 bsp 【摘要】WebGIS優勢是通過互聯網對地理空間數據進行發布和應用,以實現空間數據的共享和相互操作。將WebGIS和富客戶端技術引入Web服務器日誌管理領域,從總體設計、數據庫設計、實現框架等幾個方面設