1. 程式人生 > >基於linux的TCP網路聊天室設計與實現

基於linux的TCP網路聊天室設計與實現

利用Linux實現基於TCP模式的網路聊天程式
主要完成的兩大組成部分為:伺服器和客戶端。

  • 伺服器程式主要負責監聽客戶端發來的訊息。
  • 客戶端需要登入到伺服器端才可以實現正常的聊天功能。該程式是利用程序以及共享記憶體來實現群傳送訊息的。

以下簡單分析一下伺服器端和客戶端兩個方面所要完成的任務。

伺服器的主要功能如下:

  1. 在特定的埠上進行監聽,等待客戶端的連線。
  2. 使用者可以配置伺服器端的監聽埠。
  3. 向連線的客戶端傳送登入成功資訊。
  4. 向已經連線到伺服器的客戶端的使用者傳送系統訊息。
  5. 使用TCP多執行緒併發伺服器,向線上的所有客戶端傳送訊息

客戶端的主要功能如下:

  1. 客戶端傳參輸入IP和埠號以及使用者名稱進行註冊
  2. 連線到已經開啟的服務的服務端
  3. 使用者可以向所有人傳送資訊
  4. 使用者可以接受伺服器傳送的系統訊息

伺服器功能描述
伺服器主要是負責監聽客戶端傳送來的訊息,利用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;
}
  1. 伺服器進行編譯執行

    伺服器進行編譯執行

  2. 客戶端進行編譯執行

    客戶端進行編譯執行

  3. 伺服器出現結果

    伺服器出現結果

  4. 另外開啟一個終端執行對客戶端程式碼編譯執行

    客戶端

相關推薦

基於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服務器日誌管理領域,從總體設計、數據庫設計、實現框架等幾個方面設