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模型同時處理tcp和udp服務
在實際工作中,伺服器需要同時監聽和處理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實現tcp和udp的例子
簡單的linux下socket程式設計,分別基於TCP和UDP協議實現的簡單程式 linux下socket程式設計可以概括為以下幾個函式的運用: socket() bind() listen
Java網路程式設計(2):TCP和UDP
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
同時使用tcp和udp回射伺服器
同時使用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