1. 程式人生 > >Linux網路程式設計--使用epoll模型同時處理tcp和udp服務

Linux網路程式設計--使用epoll模型同時處理tcp和udp服務

在實際工作中,伺服器需要同時監聽和處理tcp和udp的套接字,同時監聽N多的埠。根據bind系統呼叫來講,一個socket只能監聽一個埠,因此要建立多個socket並繫結到各個埠上。當然同一個埠可以同時繫結tcp和udp的socket,但是要建立兩個socket,一個是tcp的一個是udp的。

下面我們就寫一個可以同時處理tcp和udp服務的回射伺服器。

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <fcntl.h> #include <stdlib.h> #include <sys/epoll.h> #include <pthread.h> #define MAX_EVENT_NUMBER 1024 #define TCP_BUFFER_SIZE 512 #define UDP_BUFFER_SIZE 1024 int setnonblocking( int
fd ) { int old_option = fcntl( fd, F_GETFL ); int new_option = old_option | O_NONBLOCK; fcntl( fd, F_SETFL, new_option ); return old_option; } void addfd( int epollfd, int fd ) { epoll_event event; event.data.fd = fd; //event.events = EPOLLIN | EPOLLET; event.events = EPOLLIN;//可讀事件,預設為LT模式,事件一般被觸發多次
epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event ); setnonblocking( fd ); } int main( int argc, char* argv[] ) { if( argc <= 2 ) { printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); return 1; } const char* ip = argv[1]; int port = atoi( argv[2] ); int ret = 0; //建立tcp套接字,並繫結 、監聽 struct sockaddr_in address; bzero( &address, sizeof( address ) ); address.sin_family = AF_INET; inet_pton( AF_INET, ip, &address.sin_addr ); address.sin_port = htons( port ); int listenfd = socket( PF_INET, SOCK_STREAM, 0 ); assert( listenfd >= 0 ); ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) ); assert( ret != -1 ); ret = listen( listenfd, 5 ); assert( ret != -1 ); //建立udp套接字,並繫結 bzero( &address, sizeof( address ) ); address.sin_family = AF_INET; inet_pton( AF_INET, ip, &address.sin_addr ); address.sin_port = htons( port ); int udpfd = socket( PF_INET, SOCK_DGRAM, 0 ); assert( udpfd >= 0 ); ret = bind( udpfd, ( struct sockaddr* )&address, sizeof( address ) ); assert( ret != -1 ); epoll_event events[ MAX_EVENT_NUMBER ]; int epollfd = epoll_create( 5 ); assert( epollfd != -1 ); //註冊tcp和udp套接字的可讀事件 addfd( epollfd, listenfd ); addfd( epollfd, udpfd ); while( 1 ) { int number = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, -1 ); if ( number < 0 ) { printf( "epoll failure\n" ); break; } for ( int i = 0; i < number; i++ ) { int sockfd = events[i].data.fd; //tcp有新的可讀事件,也即接受到了新的連線 if ( sockfd == listenfd ) { struct sockaddr_in client_address; socklen_t client_addrlength = sizeof( client_address ); int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength ); //將新的連線套接字也註冊可讀事件 addfd( epollfd, connfd ); } //udp套接字事件處理 else if ( sockfd == udpfd ) { char buf[ UDP_BUFFER_SIZE ]; memset( buf, '\0', UDP_BUFFER_SIZE ); struct sockaddr_in client_address; socklen_t client_addrlength = sizeof( client_address ); ret = recvfrom( udpfd, buf, UDP_BUFFER_SIZE-1, 0, ( struct sockaddr* )&client_address, &client_addrlength ); if( ret > 0 ) { sendto( udpfd, buf, UDP_BUFFER_SIZE-1, 0, ( struct sockaddr* )&client_address, client_addrlength ); } } //註冊的socket發生可讀事件 else if ( events[i].events & EPOLLIN ) { char buf[ TCP_BUFFER_SIZE ]; while( 1 ) { memset( buf, '\0', TCP_BUFFER_SIZE ); ret = recv( sockfd, buf, TCP_BUFFER_SIZE-1, 0 ); if( ret < 0 ) { //資料接受完畢之後進入下一次可讀事件 if( ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) ) { break; } close( sockfd ); break; } //服務端已經斷開連線,所以斷開客戶端連線 else if( ret == 0 ) { close( sockfd ); } else { send( sockfd, buf, ret, 0 ); } } } else { printf( "something else happened \n" ); } } } close( listenfd ); return 0; }

相關推薦

Linux網路程式設計--使用epoll模型同時處理tcpudp服務

在實際工作中,伺服器需要同時監聽和處理tcp和udp的套接字,同時監聽N多的埠。根據bind系統呼叫來講,一個socket只能監聽一個埠,因此要建立多個socket並繫結到各個埠上。當然同一個埠可以同時繫結tcp和udp的socket,但是要建立兩個socket

Linux網路程式設計--epoll 模型原理詳解以及例項

1.簡介 Linux I/O多路複用技術在比較多的TCP網路伺服器中有使用,即比較多的用到select函式。Linux 2.6核心中有提高網路I/O效能的新方法,即epoll 。 epoll是什麼?按照man手冊的說法是為處理大批量控制代碼而作了改進

Linux網路程式設計epoll模型

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/epoll.h> #include <errno.h>

linux下C/C++網路程式設計基本:socket實現tcpudp的例子

簡單的linux下socket程式設計,分別基於TCP和UDP協議實現的簡單程式 linux下socket程式設計可以概括為以下幾個函式的運用: socket() bind() listen

Java網路程式設計(2):TCPUDP

1、多執行緒“服務端-客戶端”   TCP客戶端使用Socket來連線伺服器和與伺服器通訊。以下為在主執行緒中將使用者輸入傳送給服務端,在建立的執行緒中將服務端發回的資料輸出來: import java.net.*; import java.io.*; class Cl

Linux網路程式設計【三】:TCP伺服器多程序多執行緒(http訪問)版本

為了讓伺服器同時接受多個客戶端訪問,所以需要多程序或者多執行緒 多程序版本: #include<unistd.h> #include<stdio.h> #include<stdlib.h> #include<sys/types.h

linux網路程式設計練習---聊天室(TCP/IP實現)

為了更深刻的鍛鍊認識TCP/IP協議,加強自己對Linux系統的網路程式設計部分的編寫程式碼能力,編寫基於控制檯的聊天視窗,用本機既當伺服器又當客戶端,先開啟一個shell,執行伺服器程式,然後再開啟一個shell視窗,執行客戶端程式,顯示連線成功,開始聊天吧。不知道為什麼

Linux網路程式設計》: connect()、listen()accept()三者之間的關係

基於 TCP 的網路程式設計開發分為伺服器端和客戶端兩部分,常見的核心步驟和流程如下:   connect()函式 對於客戶端的 connect() 函式,該函式的功能為客戶端主動連線伺服器,建立連線是通過三次握手,而這個連線的過程是由核心完成,不是這個函式完

Boost.Asio C++ 網路程式設計之十:基於TCP的非同步服務

       這個流程圖是相當複雜的:從Boost.Asio出來你可以看到4個箭頭指向on_accept,on_read,on_write和on_check_ping。這也就意味著你永遠不知道哪個非同步呼叫是下一個完成的呼叫,但是你可以確定的是它是這4個操作中的一個。基於TC

同時使用tcpudp回射伺服器

同時使用select函式的tcp和udp回射伺服器: #include <iostream> #include <sys/socket.h> #include <sys/types.h> #include <str

Linux網路程式設計TCP客戶/伺服器模型及基本socket函式

TCP客戶/伺服器模型 TCP連線的分組交換 在使用socket API的時候應該清楚應用程式和TCP協議棧是如何互動的: 呼叫connect()會發出SYN段(SYN是TCP報文段頭部的一個標誌位,置為1) 阻塞的read()函式返回0就表明收到了FIN段 客戶端呼叫c

嵌入式Linux網路程式設計網路基礎,OSI七層模型TCP/IP四層模型TCP/IP通訊模型、協議結構、封包與拆包,TCP/UDP協議特點及適用情況

文章目錄 1,TCP協議分成了兩個不同的協議----->TCP/IP協議誕生 2,網路的體系結構 2.1,OSI開放系統互聯模型 2.2,TCP/IP協議族的體系結構 3,TCP/IP協議通訊模型 3.1

Linux網路程式設計---I/O複用模型epoll

Linux網路程式設計—I/O複用模型之epoll 1. epoll模型簡介 epoll是Linux多路服用IO介面select/poll的加強版,e對應的英文單詞就是enhancement,中文翻譯為增強,加強,提高,充實的意思。所以epoll模型會顯

Linux網路程式設計---深刻理解5種基本IO模型

Linux五種IO模型 理解這五種I/O模型之前,我們得先清楚一個IO事件發生,它會經歷哪些步驟: 對於一個網路IO(network IO) (這裡我們以read舉例),它會涉及到兩個系統物件,一個是呼叫這個IO的process (or thread),另一個就是系統核心(kerne

Linux網路程式設計---詳解TCP的三次握手四次揮手

我們知道,在TCP/IP協議中,TCP協議提供可靠的連線服務,是因為它有許多保證可靠連線的機制。可以分為3個方面: 1.確認應答機制:指的是不管哪一端傳送資料都需要確認回覆一下。 2.超時重傳機制,傳送後等待一段時間,不管是傳送失敗或者是還沒有收到回覆,那麼就認為資料傳輸失敗了;此時將會

Linux網路程式設計TCP程式設計

直接上程式碼如下所示: 1、標頭檔案定義 #ifndef __HEAD_NET_H__ #define __HEAD_NET_H__ #include <stdio.h> #include <string.h> #include <stdlib.h>

Linux網路程式設計之IO模型

本文基於IO訪問中存在的兩個階段詳細介紹了Linux產生的五種IO模型。 上篇文章回顧: 小米開源監控Open-Falcon收錄汽車之家貢獻的Win版Agent 同步與非同步 同步是指一個任務的完成需要依賴另外一個任務時,只有等待被依賴的任務完成後

linux網路程式設計TCP狀態轉換及埠複用

(1)TCP狀態轉換圖               其中圖中分為三種狀態:實線代表的主動發起連線,虛線代表的被動發起連線,細實線代表的可以雙向發起連線的狀態。 主動發起連線方狀態變化:1)主動發起連線的一方傳送SYN標誌位,進入SYN_SENT狀態,等待接收被髮起連線方

Linux 網路程式設計 全解(三)--------TCP三次握手、資料傳輸、四次揮手、滑動視窗

寫在前面:今天中秋佳節,首先祝大家佳節快樂,身體健康,恭喜發財。吃也吃了,喝也喝了,玩也玩了,乾點正事吧。 說一下寫這個系列的目的,隨著對物聯網開發的深入,越來越覺得自己網路基礎知識的薄弱,雖然開發過程中不需要對網路基礎有很深入的瞭解照樣能進行,但有一些問題仍然是不知其因,

linux網路程式設計基礎-常用函式錯誤處理封裝

my.c #include <stdlib.h> #include <errno.h> #include <sys/socket.h> #include <sys/types.h> void perr_ex