1. 程式人生 > >libevent多執行緒伺服器

libevent多執行緒伺服器

伺服器端程式碼:

#include "lib_net.h"
#include "lib_thread.h"
#include "lib_public.h"
#include<event.h>  
#include<event2/util.h>

#define BACKLOG 10
#define MAX_EVENTS 500

char ip[24];
short port;

struct st_listenserv
{
    int sockfd;
    struct event *ev_listen;
    struct event_base *base;
};

struct st_connserv
{
    int clifd;
    struct event_base *base;
    struct event *ev_read;
    struct event *ev_write;
    char buf[1024];
};

void initsocket(struct st_listenserv *listenserv);
void accept_cb(int fd, short events, void *arg);
void read_cb(int fd, short events, void *arg);
void send_cb(int fd, short events, void *arg);
void start_thrd(int fd);
void thrd_readwrite(int sockfd);
void release_read(struct st_connserv *connserv);
void release_write(struct st_connserv *connserv);

int main(int argc, char *argv[])
{
    
    if(argc < 1)
    {
        perror("input server  port");
        return -1;
    }
    memcpy(ip, argv[1], 24);
    port = atoi(argv[2]);
    struct st_listenserv listenserv;
    initsocket(&listenserv);
    listenserv.base = event_base_new();
    listenserv.ev_listen = event_new(listenserv.base, listenserv.sockfd,EV_READ | EV_PERSIST,accept_cb,NULL);
    event_add(listenserv.ev_listen, NULL);
    event_base_dispatch(listenserv.base);
    
}

void initsocket(struct st_listenserv *listenserv)
{
    listenserv->sockfd = lib_tcpsrv_init(ip,port);
    if(listenserv->sockfd < 0)
    {
        perror("server create socket error");
        return;
    }
    if(lib_set_nonblock(listenserv->sockfd) < 0)
    {
        perror("set nonblock error");
        return;
    }
    printf("init socket ok\n");
}

void accept_cb(int fd, short events, void *arg)
{
    struct sockaddr_in cin;
    socklen_t socklen = sizeof(cin);
    int clifd = lib_tcpsrv_accept(fd, &cin);
    if(clifd <0)
    {
        perror("accept error");
    }
    if(lib_set_nonblock(clifd) < 0)
    {
        perror("set nonblock error");
        return;
    }
    printf("new conneciotn [%s:%d]\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));
    start_thrd(clifd);
}

void start_thrd(int fd)
{
    pthread_t pid;
    lib_thread_create(&pid, thrd_readwrite, (void*)fd, 1);    
}

void thrd_readwrite(int sockfd)
{

    struct st_connserv connserv;
    connserv.clifd = sockfd;
    connserv.base = event_base_new();
    connserv.ev_read = event_new(connserv.base, connserv.clifd, EV_READ|EV_PERSIST, read_cb, &connserv);
    event_add(connserv.ev_read,NULL);
    event_base_dispatch(connserv.base);
}

void read_cb(int fd, short events, void *arg)
{

    struct st_connserv *conn = (struct st_connserv*)arg;
    int recvlen = lib_tcp_recv(conn->clifd, conn->buf,1024, -1);
    if(recvlen < 0)
    {
        perror("recv error");
        close(conn->clifd);
        release_read(conn);
    }
    printf("recv data:%s\n", conn->buf);
    
    conn->ev_write = event_new(conn->base, conn->clifd, EV_WRITE, send_cb, conn);
    event_add(conn->ev_write, NULL);
}

void send_cb(int fd, short events, void *arg)
{
    struct st_connserv *conn = (struct st_connserv*)arg;
    int sendlen = lib_tcp_send(conn->clifd, conn->buf, 1024);
    if(sendlen < 0)
    {
        perror("send error");
        close(conn->clifd);
        release_write(conn);
    }
}

void release_read(struct st_connserv *connserv)
{
    if(connserv == NULL)
    {
        return;
    }
    event_del(connserv->ev_read);
    event_base_loopexit(connserv->base, NULL);
    if(NULL != connserv->ev_read){
        free(connserv->ev_read);
    }
    event_base_free(connserv->base);
    free(connserv);
    
}

void release_write(struct st_connserv *connserv)
{
    if(connserv != NULL)
    {
        event_del(connserv->ev_write);
        free(connserv->ev_write);
        free(connserv);
    }
}


完整程式碼地址:https://github.com/Addision/test_libevent_thrd_server

簡單客戶端程式碼:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define PORT 9999
#define IPADDR "127.0.0.1"
int main(int argc, char *argv[])
{
    /*  套接字描述符*/
    int sockfd, numbytes;
	char buf[1024];
    struct sockaddr_in their_addr;  

    if ((sockfd = socket(AF_INET,SOCK_STREAM, 0)) == -1) 
    {
        perror("socket");
        exit(1);
    }

    their_addr.sin_family = AF_INET;
    /*  網路位元組順序,短整型*/
    their_addr.sin_port = htons(PORT);
    their_addr.sin_addr.s_addr = inet_addr(IPADDR);
    /*  將結構剩下的部分清零*/
    bzero(&(their_addr.sin_zero),8);
    if(connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1)
    {
        perror("connect");
        exit(1);
    }
	int ret = send(sockfd, "123456", 6,0);
	if(ret > 0)
	{
		printf("send ok\n");
	}
	ret = recv(sockfd, buf, 1024,0);
	if(ret > 0)
	{
		printf("recv data %s\n", buf);
	}
    getchar();
    return 0;
}


相關推薦

libevent執行伺服器

伺服器端程式碼: #include "lib_net.h" #include "lib_thread.h" #include "lib_public.h" #include<event.h>   #include<event2/util.h> #

multi-reactor伺服器模型的C++封裝類(libevent+執行實現)

最近在看memcached的原始碼,覺得它那種libevent+多執行緒的伺服器模型(multi-reactor)真的很不錯,我將這個模型封裝成一個C++類,根據我的簡單測試,這個模型的效率真的很不錯,歡迎大家試用。 這個類的使用方法很簡單(缺點是不太靈活),只

使用libevent執行驗證Linux上的伺服器"驚群"現象

什麼是驚群現象? 驚群(thundering herd)是指,只有一個子程序能獲得連線,但所有N個子程序卻都被喚醒了,這種情況將使效能受損。 舉一個很簡單的例子,當你往一群鴿子中間扔一塊食物,雖然最終只有一個鴿子搶到食物,但所有鴿子都會被驚動來爭奪,沒有搶到食物的鴿子只好回

Qt TCP通訊,執行伺服器

相信許多初學Qt的同學都會和我一樣遇到這樣的問題: 一、Qt TCP通訊在使用nextPendingConnect後,伺服器端就只會與最後接入的客戶端通訊,這個時候就會考慮繼承QThread實現多執行緒,從而實現多個客戶端與伺服器端通訊,每當一個新的客戶端連線時,通過標識碼socke

windows下Libevent +執行(負載均衡分配法) 之檔案傳輸

一、先說一下服務端的流程: 1、主執行緒負責監聽客戶端的連線; 2、當有客戶端連線時,主執行緒通過管道向相應的子執行緒傳送監聽套接字描述符,子執行緒通過負載均衡法選擇出來; 3、當主執行緒傳送監聽描述符時,子執行緒的讀管道回撥函式會被回撥; 4、子執行緒為收到的監聽描述符設定讀取

用 threading 寫執行伺服器

import socket import threading   server = socket.socket() server.bind(("127.0.0.1",8899)) server.listen(1000)   def func(conn):   while T

執行伺服器

#coding=utf-8 from socket import * from threading import Thread from time import sleep # 處理客戶端的請求並執行事情 def dealWithClient(newSocket,destAddr):

Qt 執行伺服器與客戶端

文章目錄 思路 伺服器 myserver.h myserver.cpp mythread.h mythread.cpp mysocket.h mysocket.cpp

C網路程式設計--執行伺服器

 伺服器主要用的是socket(雙向的通訊的一端),bind(繫結),listen(切換監聽狀態),accept(與客戶端取得連線) 將accept放入多執行緒,可以多個客戶端連線 #include <stdio.h> //標準輸入輸出 #incl

windows下 Libevent +執行 實現檔案傳輸

1、模式:來一個客戶端連線進來,服務端就開啟一個處理執行緒。 2、缺點:對大量的客戶端情況不適用。大量客戶端的情況需要加入執行緒管理機制。 // LibeventTest.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #incl

TCP/IP網路程式設計 基於Linux程式設計_4 --執行伺服器端的實現

執行緒基本概念 前面我們講過多程序伺服器,但我們知道它開銷很大,因此我們才引入執行緒,我們可以把它看成是一種輕量級程序。它相比程序有如下幾個優點: 執行緒的建立和上下文切換開銷更小且速度更快。 執行緒間交換資料時無需特殊技術。 程序:在作業系統構成

linux tcp執行伺服器與客戶端程式設計例項

伺服器端: #include<iostream> #include<arpa/inet.h> #include<sys/socket.h> #include<cstdlib> #include<cstdio> #i

【muduo】執行伺服器的適用場合與程式設計模型

文章目錄 一、程序與執行緒 1、程序的概念 2、關於程序的一個形象比喻(人) 3、執行緒的概念 二、多程序和多執行緒的適用場景 1、需要頻繁建立銷燬的優先用執行緒 2、

基於非阻塞socket的執行伺服器的實現------一個伺服器如何與個客戶端進行通訊?

      我們首先來看服務端(涉及非阻塞socket和多執行緒): #include <stdio.h> #include <winsock2.h> #include <windows.h> #pragma comment(li

Linux執行伺服器-門禁打卡系統

原始碼地址 系統採用一個伺服器+兩種客戶端(網頁+APP),執行在樹莓派2上 OpenDoorMultiThreadServer OpenDoorMultiThreadServer 實驗室門禁打卡系統 1、mydb是操作資料庫Mysql類,表示每個

執行伺服器模型

本文主要講我個人在多執行緒開發方面的一些粗淺經驗。總結了一兩種常用的執行緒模型,歸納了程序間通訊與執行緒同步的最佳實踐,以期用簡單規範的方式開發多執行緒程式。 文中的“多執行緒伺服器”是指執行在 Linux 作業系統上的獨佔式網路應用程式。硬體平臺為 Int

tcp/ip 執行伺服器端的實現(參考tcp/ip網路程式設計)

執行緒的切換比程序快的多,因為它不需要切換資料區和堆 共享資料區和堆可以用來交換資訊 一、執行緒的建立 pthread_create()函式 #include<pthread.h> int prthread_create(pthread * thread,c

Python TCP 客戶端(配合socket執行伺服器)

''' Python TCP 客戶端(配合socket多執行緒伺服器) by 鄭瑞國 1、建立網路套接字c 2、建立網路連線 3、收發資訊 ''' import socket c = socket.socket() #1、建立網路套接字c c.connect(('127.

Python socket TCP執行伺服器

''' Python socket TCP多執行緒伺服器 by 鄭瑞國 1、建立網路套接字s 2、繫結地址 3、監聽 4、接受客戶端連線 5、多執行緒處理客戶端訊息 ''' import socket import threading s = socket.socket()

java網路程式設計:9、基於TCP的socket程式設計(二)伺服器端迴圈監聽接收個客戶端_執行伺服器程式

宣告:本教程不收取任何費用,歡迎轉載,尊重作者勞動成果,不得用於商業用途,侵權必究!!! 文章目錄 一、核心程式碼編寫 1、伺服器端程式的編寫 2、客戶端程式的編寫 3、測試列印輸出 二、系列文章(java網路程式設計) 上篇講了基於tcp的程式設計的一些基礎知識