linux中select函数 实现多用户通信
来源:互联网 发布:软件售前 编辑:程序博客网 时间:2024/06/05 07:16
Select服务器实现多人通信的原理:
用户与服务器之间需要动态建立三条管道,第一条管道用于判断用户是否上线,如果用户n上线则在server.fifo中写入on以及用户id,然后建立专门用来发信息和收信息的管道,并将用户n加入用户链表。用户n通过发信息管道向服务器发信息,服务器收到信息后,将信息发送给目前在线的所有用户。用户个数即链表中结点个数。
代码如下:
1、头文件
#ifndef __SER_H__
#define __SER_H__
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<sys/select.h>
#include<sys/time.h>
#define PIPE_PATH "/home/comst/pipe"
#define PIPE_NAME "server.fifo"
typedef struct tag
{
int m_id ;
int m_send;
int m_recv;
struct tag* m_next ;
}CLIENT, *pCLIENT;
void distpatch_msg(pCLIENT phead, char* msg);
#endif
2、服务器server.c
/*************************************************************************
> File Name: ./src/server.c
> Author: Comst
> Mail:750145240@qq.com
> Created Time: Sun 01 Feb 2015 04:41:48 PM CST
************************************************************************/
#include"my_server.h"
int main(int argc, char* argv[])
{
int fd_listen ;
char path_name[128] = "" ;
char fifo_name[128] ;
char msg[1024];
char client_stat[5] = "";
int client_pid ;
sprintf(path_name, "%s/%s", PIPE_PATH, PIPE_NAME);
mkfifo(path_name, 0666);
printf("mkfifo over!\n");
fd_listen = open(path_name, O_RDONLY);
if(fd_listen == -1)
{
printf("open server_fifo fail!\n");
exit(1);
}
pCLIENT plist = NULL, pcur, pnew, ppre ;
fd_set rd_sets, bak_sets;
FD_ZERO(&rd_sets);
FD_ZERO(&bak_sets);
FD_SET(fd_listen, &rd_sets);
while(1)
{
bak_sets = rd_sets ;
printf("selecting...\n");
select(1024, &bak_sets, NULL, NULL, NULL);
if(FD_ISSET(fd_listen, &bak_sets))
{
memset(msg,0, 1024);
if( read(fd_listen, msg, 1024) == 0 )
{
printf("no clients!\n");
continue ;
}
//
memset(client_stat, 0, sizeof(client_stat));
sscanf(msg, "%d%s", &client_pid, client_stat);
if(strncmp("on", client_stat, 2) == 0)// client on "pid on\n"
{// pid_r.fifo(c_r - s_w) pid_w.fifo(c_w - s_r)
printf("client: %d on\n", client_pid);
memset(fifo_name, 0, 128) ;
sprintf(fifo_name, "%d_r.fifo", client_pid);
memset(path_name, 0, 128) ;
sprintf(path_name, "%s/%s", PIPE_PATH, fifo_name);
pnew = (pCLIENT)calloc(1, sizeof(CLIENT));
pnew ->m_id = client_pid ;
printf("pid_r.fifo: %s\n", path_name);
pnew ->m_send = open(path_name, O_WRONLY);
printf("send_fd: %d\n", pnew ->m_send);
memset(fifo_name, 0, 128) ;
sprintf(fifo_name, "%d_w.fifo", client_pid);
memset(path_name, 0, 128) ;
sprintf(path_name, "%s/%s", PIPE_PATH, fifo_name);
printf("pid_w.fifo: %s\n", path_name);
pnew ->m_recv = open(path_name, O_RDONLY);
printf("recv_fd: %d\n", pnew ->m_recv);
printf("open client fifo: %d, %d\n", pnew ->m_send, pnew ->m_recv);
FD_SET(pnew ->m_recv, &rd_sets);
pnew ->m_next = plist ;
plist = pnew ;
}else//client off "pid off\n"
{
printf("client: %d off\n", client_pid);
ppre = NULL ;
pcur = plist ;
while(pcur && pcur ->m_id != client_pid)
{
ppre = pcur ;
pcur = pcur ->m_next ;
}
if(pcur == NULL)
{
printf("not exist!\n");
continue ;
}else
{
if(ppre == NULL)
{
plist = pcur ->m_next ;
}else
{
ppre ->m_next = pcur ->m_next ;
}
close(pcur ->m_send) ;
close(pcur ->m_recv) ;
FD_CLR(pcur ->m_recv, &rd_sets);
free(pcur);
printf("clear ok !\n");
}
}
}
pcur = plist ;
while(pcur)
{
if(FD_ISSET(pcur ->m_recv, &bak_sets))// translate
{
memset(msg, 0, 1024);
read(pcur -> m_recv, msg, 1024);
dispatch_msg(plist, msg);
}
pcur = pcur ->m_next ;
}
}
return 0 ;
}
3、用户client.c
/*************************************************************************
> File Name: client.c
> Author: Comst
> Mail:750145240@qq.com
> Created Time: Sun 01 Feb 2015 06:04:36 PM CST
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<sys/select.h>
#include<sys/time.h>
#define PIPE_PATH "/home/comst/pipe"
#define PIPE_NAME "server.fifo"
int main(int argc, char* argv[])
{
int fd_server ;
char path_name[128]="";
char fifo_name[128] ;
char msg[1024] ="" ;
int fd_recv, fd_send ;
sprintf(path_name, "%s/%s", PIPE_PATH, PIPE_NAME);
fd_server = open(path_name, O_WRONLY);
if(fd_server == -1)
{
printf("open fail!\n");
exit(1) ;
}
// pid_r.fifo pid_w.fifo
//
memset(fifo_name, 0, 128);
sprintf(fifo_name, "%u_r.fifo", getpid());
memset(path_name, 0, sizeof(path_name));
sprintf(path_name, "%s/%s", PIPE_PATH, fifo_name);
if(-1 == mkfifo(path_name, 0666) )
{
printf("mkfif fail: %s\n", path_name);
exit(1) ;
}
printf("%s open\n", path_name);
memset(fifo_name, 0, 128);
sprintf(fifo_name, "%u_w.fifo", getpid());
memset(path_name, 0, sizeof(path_name));
sprintf(path_name, "%s/%s", PIPE_PATH, fifo_name);
if(mkfifo(path_name, 0666) == -1 )
{
printf("mkfif fail: %s\n", path_name);
exit(1) ;
}
printf("%s open\n", path_name);
printf("mkfifo over!\n");
sprintf(msg, "%u on\n", getpid());
printf("msg: %s\n", msg);
write(fd_server, msg, strlen(msg));
memset(fifo_name, 0, 128);
sprintf(fifo_name, "%u_r.fifo", getpid());
memset(path_name, 0, sizeof(path_name));
sprintf(path_name, "%s/%s", PIPE_PATH, fifo_name);
fd_recv = open(path_name, O_RDONLY);
memset(fifo_name, 0, 128);
sprintf(fifo_name, "%u_w.fifo", getpid());
memset(path_name, 0, sizeof(path_name));
sprintf(path_name, "%s/%s", PIPE_PATH, fifo_name);
fd_send = open(path_name, O_WRONLY);
printf("fifo open %d %d\n", fd_send, fd_recv);
fd_set rd_sets ;
FD_ZERO(&rd_sets);
while(1)
{
FD_SET(0, &rd_sets);
FD_SET(fd_recv, &rd_sets);
select(1024, &rd_sets, NULL, NULL, NULL);
if(FD_ISSET(0, &rd_sets))
{
memset(msg, 0, sizeof(msg)) ;
sprintf(msg, "from %u: ", getpid());
read(0, msg + strlen(msg), 1024 - strlen(msg) );
write(fd_send, msg, strlen(msg));
}
if(FD_ISSET(fd_recv, &rd_sets))
{
memset(msg, 0, sizeof(msg)) ;
read(fd_recv, msg, 1024);
write(1, msg, strlen(msg));
}
}
}
4、转发函数func.c
/*************************************************************************
> File Name: ./func.c
> Author: Comst
> Mail:750145240@qq.com
> Created Time: Sun 01 Feb 2015 05:57:36 PM CST
************************************************************************/
#include"my_server.h"
void dispatch_msg(pCLIENT phead, char* msg)
{
while(phead)
{
write(phead ->m_send, msg, strlen(msg));
phead = phead ->m_next ;
}
}
注:宏定义 #define PIPE_PATH "/home/comst/pipe" 在不同的文件系统中路径不同,读者应根据具体情况定义。
- linux中select函数 实现多用户通信
- Linux下poll函数实现多用户聊天
- linux中select网络通信
- Linux中select()函数
- Linux中select函数
- Linux中select函数
- linux下使用socket中的select完成单线程单进程多用户之间通信
- linux 多用户间的通信
- linux多用户之间对话/通信
- select函数 实现三用户简单通信
- c++中Socket通信函数之select
- c++中Socket通信函数之select
- c++中Socket通信函数之select
- linux select()函数实现分析
- linux select()函数实现分析
- linux select()函数实现分析
- linux—TCP_server端编写之利用select()函数编写可多用户同时访问
- [转]Linux 下给类tcp 通信模式的实现。select 函数
- Unity3D游戏开发——Asset Server搭建
- BZOJ1022 [SHOI2008]小约翰的游戏John(Anti-Nim游戏)
- Unity3D的几种坐标系
- Unity3D ShaderLab 创建自定义高光类型
- Java 内存分配全面浅析
- linux中select函数 实现多用户通信
- Unity3D学习笔记——Unity3D的窗口布局
- Unity3D ShaderLab法线贴图
- 莫言诺贝尔获奖词——看莫言对中国的描述方式
- POJ3617(字典序最小问题)
- C++中多线程与Singleton的那些事儿
- NGUI之Slider,最简单的方法做进度条。
- Unity3D着色器Shader编程入门
- 【hiho】1114