linux 高级服务器编程,Linux 高级I/O之poll函数及简单服务器客户端编程

当需要同时监听多个文件描述符时,就需要I/O复用函数,I/O复用函数有select、poll、epoll,今天主要使用poll函数。

poll()接受一个指向结构'struct pollfd'列表的指针,其中包括了你想测试的文件描述符和事件。事件由一个在结构中事件域的比特掩码确定。当前的结构在调用后将被填写并在事件发生后返回。

函数原型:#include

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

struct pollfd{

int fd;         /*file descriptor*/

short events;   /*requested events*/

short revents;  /*returned events*/

}

函数参数:fds是要监听的fd的数组,nfds是数组个数,timeout 超时时间 -1是阻塞;

函数说用:通过传入的events的类型去判断返回的类型是否一致,如果一致就该干事了。

events:

常量说明

POLLIN普通或优先级带数据可读

POLLRDNORM普通数据可读

POLLRDBAND优先级带数据可读

POLLPRI高优先级数据可读

POLLOUT普通数据可写

POLLWRNORM普通数据可写

POLLWRBAND优先级带数据可写

POLLERR发生错误

POLLHUP发生挂起

POLLNVAL描述字不是一个打开的文件

接下来是是一个服务器监听两个socket的例子:

服务器代码:#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define MAX_POLLFD_NUM 2

//#define SERVER_CONN_IP1 "1.1.1.1"

//#define SERVER_CONN_IP2 "1.1.1.1"

#define DEFAULT_PORT 8000

#define BUFF_MAX 1024

typedef void(*Server_Rrocess_Thread_Fun)(void *arg);

/*thread process function define */

typedef struct sever_thread_fun{

Server_Rrocess_Thread_Fun Server_Process_Client_Conn1;

Server_Rrocess_Thread_Fun Server_Process_Client_Conn2;

}Poll_Server_Process_Clinet_FUN_t;

/*connect 1 thread function*/

void *Poll_Conn1_Process(void *arg)

{

unsigned char ucBufArr[BUFF_MAX] = {0};

unsigned long ulSize = 0;

int connect_fd ;

printf("come pthread conn1 fun to proess conn1\n");

if( (connect_fd = accept( *(int*)arg, (struct sockaddr*)NULL, NULL)) == -1){

printf("accept socket error: %s(errno: %d)",strerror(errno),errno);

}

ulSize = recv(connect_fd, ucBufArr, BUFF_MAX, 0);

if(send(connect_fd, "Hello,you are connected 1!\n", 26,0) == -1)

perror("send error");

ucBufArr[ulSize] = '\0';

//sleep(20);

printf("recv msg from client: %s\n", ucBufArr);

close(connect_fd);

pthread_exit((void*)1);

}

/*connect 1 thread function*/

void *Poll_Conn2_Process(void *arg)

{

unsigned char ucBufArr[BUFF_MAX] = {0};

unsigned long ulSize = 0;

int connect_fd ;

printf("come pthread conn2 fun to proess conn2\n");

if( (connect_fd = accept( *(int*)arg, (struct sockaddr*)NULL, NULL)) == -1){

printf("accept socket error: %s(errno: %d)",strerror(errno),errno);

}

ulSize = recv(connect_fd, ucBufArr, BUFF_MAX, 0);

if(send(connect_fd, "Hello,you are connected 2!\n", 26,0) == -1)

perror("send error");

ucBufArr[ulSize] = '\0';

// sleep(20);

printf("recv msg from client: %s\n", ucBufArr);

close(connect_fd);

pthread_exit((void*)2);

}

int main()

{

int poll_ret = 0;

pthread_t thread_conn1;

pthread_t thread_conn2;

/*socket var*/

int server_socket_fd_conn1;

int server_socket_fd_conn2;

struct sockaddr_in servaddr_conn1;

struct sockaddr_in serveraddr_conn2;

/*poll var*/

struct pollfd pollfd_arr[MAX_POLLFD_NUM];

/*init thread fun*/

Poll_Server_Process_Clinet_FUN_t server_conn_handel;

server_conn_handel.Server_Process_Client_Conn1 = Poll_Conn1_Process;

server_conn_handel.Server_Process_Client_Conn2 = Poll_Conn2_Process;

/*create two server socket*/

if( (server_socket_fd_conn1 = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){

printf("create socket conn1 error: %s(errno: %d)\n",strerror(errno),errno);

exit(0);

}

if( (server_socket_fd_conn2 = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){

printf("create socket conn2 error: %s(errno: %d)\n",strerror(errno),errno);

exit(0);

}

/*init socket 1 for conn1*/

memset(&servaddr_conn1, 0, sizeof(servaddr_conn1));

servaddr_conn1.sin_family = AF_INET;

servaddr_conn1.sin_addr.s_addr = htonl(INADDR_ANY);

servaddr_conn1.sin_port = htons(DEFAULT_PORT);

//if( inet_pton(AF_INET, SERVER_CONN_IP1, &servaddr_conn1.sin_addr.s_addr) <= 0){

//   printf("inet_pton error for %s\n",SERVER_CONN_IP1);

//  exit(0);

// }

/*init socket 2 for conn2*/

memset(&serveraddr_conn2, 0, sizeof(serveraddr_conn2));

serveraddr_conn2.sin_family = AF_INET;

serveraddr_conn2.sin_addr.s_addr = htonl(INADDR_ANY);

serveraddr_conn2.sin_port = htons(DEFAULT_PORT+1);

//if( inet_pton(AF_INET, SERVER_CONN_IP2, &serveraddr_conn2.sin_addr.s_addr) <= 0){

//   printf("inet_pton error for %s\n",SERVER_CONN_IP2);

//  exit(0);

// }

/*bind connect 1 socket*/

if( bind(server_socket_fd_conn1, (struct sockaddr*)&servaddr_conn1, sizeof(servaddr_conn1)) == -1){

printf("bind socket error1: %s(errno: %d)\n",strerror(errno),errno);

exit(0);

}

/*bind connect 2 socket*/

if( bind(server_socket_fd_conn2, (struct sockaddr*)&serveraddr_conn2, sizeof(serveraddr_conn2)) == -1){

printf("bind socket error2: %s(errno: %d)\n",strerror(errno),errno);

exit(0);

}

/*listen connect 1*/

if( listen(server_socket_fd_conn1, 10) == -1){

printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);

exit(0);

}

/*listen connect 2*/

if( listen(server_socket_fd_conn2, 10) == -1){

printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);

exit(0);

}

pollfd_arr[0].events = POLLRDNORM;/*only read event*/

pollfd_arr[0].fd = server_socket_fd_conn1;

pollfd_arr[1].events = POLLRDNORM;/*only read event*/

pollfd_arr[1].fd = server_socket_fd_conn2;

while(1)

{

poll_ret = poll( pollfd_arr, MAX_POLLFD_NUM,-1);

if( pollfd_arr[0].revents & POLLRDNORM )

{

/*connect 1 process task*/

pthread_create( &thread_conn1, NULL, server_conn_handel.Server_Process_Client_Conn1, (void *)(&pollfd_arr[0].fd));

}

if( pollfd_arr[1].revents & POLLRDNORM )

{

/*connect 2 process task*/

pthread_create( &thread_conn2, NULL, server_conn_handel.Server_Process_Client_Conn2, (void *)(&pollfd_arr[1].fd));

}

sleep(1);

}

return 0;

}

客户端代码:#include

#include

#include

#include

#include

#include

#include

#define BUFF_MAX 1024

#define DEFAULT_PORT 8000

int main(int argc, char** argv)

{

int    sockfd, n,rec_len;

char    recvline[BUFF_MAX], sendline[BUFF_MAX];

char    buf[BUFF_MAX];

struct sockaddr_in    servaddr;

if( argc != 2){

printf("usage: ./client \n");

exit(0);

}

/*create socket*/

if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) 

printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);

exit(0);

}

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(DEFAULT_PORT/*+1/);/*DEFAULT_PORT is connect 1 to server,DEFAULT_PORT+1 is connect 2 to server*/

/*string ip to int ip*/

if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){

printf("inet_pton error for %s\n",argv[1]);

exit(0);

}

/*connect server*/

if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) 

printf("connect error: %s(errno: %d)\n",strerror(errno),errno);

exit(0);

}

printf("send msg to server: \n");

fgets(sendline, BUFF_MAX, stdin);

/*write data to sockfd*/

if( send(sockfd, sendline, strlen(sendline), 0) 

{

printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);

exit(0);

}

/*read socket data*/

if((rec_len = recv(sockfd, buf, BUFF_MAX,0)) == -1) {

perror("recv error");

exit(1);

}

buf[rec_len]  = '\0';

printf("Received : %s \n",buf);

/*colse socket*/

close(sockfd);

exit(0);

}

解释:服务器端监听 ip 127.0.0.1 port 8000和ip 127.0.0.1 port 8001

结果演示:

a6f1506a9b7a4be301df7f7e1c9345aa.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值