基於epoll的聊天室總結

2021-10-06 10:38:39 字數 4269 閱讀 7956

epoll實現高併發聊天室建立了乙個ipv4套接字位址

//使用者連線的伺服器 ip + port

struct sockaddr_in serveraddr;

將伺服器的ip位址和埠號填入套接字位址結構

serveraddr.sin_family = pf_inet;

serveraddr.sin_port =

htons

(server_port)

;// htons返回網路位元組序

// inet_addr已被廢棄

// serveraddr.sin_addr.s_addr = inet_addr(server_ip);

inet_aton

(server_ip,

(struct in_addr*

)&serveraddr.sin_addr.s_addr)

;

建立tcp套接字,通過指定使用的協議族套接字型別使用對應的傳輸協議:

//建立socket套接字,使用tcp傳輸協議,返回套接字描述符,類似於檔案描述符

int listener =

socket

(pf_inet, sock_stream,0)

;

將套接字位址結構繫結到套接字上

//繫結位址if(

bind

(listener,

(const

struct sockaddr *

)&serveraddr,

sizeof

(serveraddr)

)<0)

socket被建立之初,被假設是乙個主動套接字,listen將乙個未連線的套接字轉化為乙個被動套接字,第二個引數5,是已排隊連線的最大數目

//監聽,下面設定的5對於現在的網路可能較小

int ret =

listen

(listener,5)

;

使用epoll_create方法建立事件表,後續的連線都將註冊到此事件表中

//在核心中建立事件表

int epfd =

epoll_create

(epoll_size);if

(epfd <0)

通過呼叫自己的addfd方法,將監聽套接字描述符填入epoll_event結構體中,並新增到事件表中

void

addfd

(int epollfd,

int fd,

bool enable_et )

//往核心事件表裡新增事件

addfd

(epfd, listener,

true

);

參考:epoll詳解

通過epoll_wait方法,將就緒事件從事件表中複製到第二個引數events陣列中。

如果是監聽套接字狀態發生變化,使用accept函式,通過監聽套接字描述符建立乙個已連線套接字描述符,並通過自己的addfd方法將已連線套接字新增到事件表中,同時新增到建立的clients_list中,方便後續進行廣播**訊息。並使用send函式給新連線的客戶端傳送歡迎訊息。

如果傳送變化的是已連線套接字,說明有客戶端傳送來的新的訊息,那麼就需要對所有除傳送訊息的客戶端進行**廣播訊息。

//主迴圈

while(1

)printf

("epoll_events_count = %d\n"

, epoll_events_count)

;//處理這epoll_events_count個就緒事件

for(

int i =

0; i < epoll_events_count;

++i)

}//客戶端喚醒//處理使用者發來的訊息,並廣播,使其他使用者收到資訊

else}}

}

進行廣播訊息的時候,要判斷recv函式的返回值,如果是0表示被動關閉,接著呼叫close方法,將客戶端進行關閉,並移出客戶端列表。如果大於0表示發來了資料,將資料對客戶端列表中除傳送方的所有客戶端進行廣播**。

// utility.h

intsendbroadcastmessage

(int clientfd)

else

//broadcast message

// format message to broadcast

sprintf

(message, server_message, clientfd, buf)

; list<

int>

::iterator it;

for(it = clients_list.

begin()

; it != clients_list.

end();

++it)}}

}return len;

}

套接字位址的建立以及和socket套接字的繫結與服務端類似,然後通過使用connect函式阻塞式主動開啟進行與服務端的連線。connect前呼叫bind函式不是必須的,核心會確定源ip,並選擇臨時埠作為源埠。

// 連線服務端if(

connect

(sock,

(struct sockaddr *

)&serveraddr,

sizeof

(serveraddr)

)<0)

使用管道進行程序間通訊,後面要乙個程序負責接收使用者的輸入,乙個程序等待伺服器的訊息

// 建立管道,fd[0]為讀而開啟,fd[1]為寫而開啟。fd[1]的輸出是fd[0]的輸入

// 打算其中fd[0]用於父程序讀,fd[1]用於子程序寫

int pipe_fd[2]

;if(pipe

(pipe_fd)

<0)

依然還是用epoll機制來監聽管道讀和套接字描述符sock是否有事件發生

// 建立epoll

int epfd =

epoll_create

(epoll_size);if

(epfd <0)

static

struct epoll_event events[2]

;//將sock和管道讀端描述符都新增到核心事件表中

addfd

(epfd, sock,

true);

addfd

(epfd, pipe_fd[0]

,true

);

使用fork函式,建立乙個父程序的副本---------子程序,一次被呼叫,但返回兩次,子程序返回0,而在父程序返回子程序的程序id

子程序負責向管道寫資料,關閉子程序的讀端

父程序負責接收資料,關閉管道的寫端,通過判斷是sock狀態傳送了變化還是管道的狀態傳送了變化,將資料顯示還是將資料傳送到服務端。

int pid =

fork()

;if(pid <0)

else

if(pid ==0)

// 子程序

// 子程序將資訊寫入管道

else}}

}else

//pid > 0 父程序

else

printf

("%s\n"

, message);}

//子程序寫入事件發生,父程序處理並傳送服務端

else}}

//for

}//while

}

通過學習此專案:學到了客戶端與服務端進行通訊的基本步驟,以及使用使用管道進行程序間通訊,管道進行通訊時需要程序有共同的祖先,在這裡是學習管道的乙個很好的例子。

基於python的聊天室

server用於中轉訊息,如果想要實現真實的聊天室,必須將server的ip設定為雲服務,或者公網ip from socket import from select import select defmain main 主函式 server socket af inet,sock stream 建立...

基於UDP聊天室程式

基於udp聊天室程式使用socket程式設計實現。windows套接字在兩種模式下執行i o操作,阻塞和非阻塞。在阻塞模式下,在i o操作完成前,執行操作的winsock函式會一直等待下去 如recvfrom,wsarecvfrom函式 不會立即返回程式 將控制權交還給程式 而在非阻塞模式下,win...

基於PHP MySQL的聊天室設計

mysql併發能力強 響應速度快,是效能優異的資料庫軟體 php是功能強大的伺服器端指令碼語言。筆者在 開發中,採用 php4.0 mysql3.23.38建立了多種應用。下面,以乙個簡單的 聊天室設計為例,介紹 php mysql在網頁開發中的應用。1 總體設計 1 1 構思與規劃 聊天室的基本原...