Linux基础——通过select实现简单的服务器与客户端

在这里,我们还是需要一个管道,只不过,我们只需这一个管道,即可知道,客户端有哪些上线、对话、下线等。

服务器端的实现代码如下:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <sys/stat.h>
  5 #include <sys/types.h>
  6 #include <fcntl.h>
  7 #include <sys/time.h>
  8 #include <sys/select.h>
  9 #include <errno.h>
 10 #define ON 1
 11 #define OFF 0
 12 int errno;
 13 typedef struct tag
 14 {
 15     int id;
 16     int fd;
 17     int type;
 18 }NODE;
 19 int main(int argc, const char *argv[])
 20 {
 21     if(mkfifo(argv[1], 0666) == -1)
 22     {
 23         printf("创建管道失败!!\n");
 24         exit(1);
 25     }
 26
 27     int fd;
 28     fd = open(argv[1], O_RDONLY);
 29     if(fd == -1)
 30     {
 31         printf("open error!!\n");
 32         exit(1);
 33     }
 34     NODE list[1024];
 35     int i;
 36     for(i = 0; i< 1024; i ++)
 37     {
 38         list[i].id = 0;
 39         list[i].type = OFF;
 40         list[i].fd = 0;
 41     }
 42     fd_set readset, ready;
 43     FD_ZERO(&readset);
 44     FD_ZERO(&ready);
 45     FD_SET(fd, &readset);
 46     struct timeval tm;
 47     char buf[128];
 48     int ret;
 49     while(1)
 50     {
 51         ready = readset;
 52         tm.tv_sec = 0;
 53         tm.tv_usec = 1000;
 54         ret = select(fd + 1, &ready, NULL, NULL, &tm);
 55         if(ret == 0)
 56             continue;
 57         else if(ret == -1)
 58         {
 59             if(errno == EINTR)
 60                 continue;
 61             break;
 62         }
 63         else
 64         {
 65             memset(buf, 0, 128);
 66             read(fd, buf, 128);
 67             if(strncmp(buf, "on", 2) == 0)
 68             {
 69                 int sfd;
 70                 char name[128];
 71                 memset(name, 0, 128);
 72                 sscanf(buf + 3, "%d", &sfd);
 73                 printf(" %d is on !!\n", sfd);
 74                 sprintf(name, "%d.fifo", sfd);
 75                 int index;
 76                 for(index = 0; index < 1024; index ++)
 77                 {
 78                     if(list[index].type == OFF)
 79                     {
 80                         list[index].id = sfd;
 81                         list[index].fd = open(name, O_WRONLY);
 82                         list[index].type = ON;
 83                         break;
 84                     }
 85                 }
 86             }
 87             else if(strncmp(buf, "off", 3) == 0)
 88             {
 89                 int sfd;
 90                 sscanf(buf + 4, "%d", &sfd);
 91                 printf("%d is off !!\n", sfd);
 92                 int index;
 93                 for(index = 0; index <1024; index ++)
 94                 {
 95                     if(list[index].id == sfd)
 96                     {
 97                         close(list[index].fd);
 98                         list[index].id = 0;
 99                         list[index].type = OFF;
100                         break;
101                     }
102                 }
103             }
104             else
105             {
106                 int sfd;
107                 sscanf(buf + 5, "%d", &sfd);
108                 int index;
109                 for(index = 0; index < 1024; index ++)
110                 {
111                     if(list[index].type == ON && list[index].id != sfd)
112                         write(list[index].fd, buf, strlen(buf));
113                 }
114             }
115         }
116     }
117     close(fd);
118     unlink(argv[1]);
119     return 0;
120 }

在这里,当ret = -1时,我们需要判断errno是否由信号中断引起的,如果是由于人为的退出,那么程序将退出,

如果是由于信号中断,程序将再次连接信号,等待数据。

客户端的实现代码如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <sys/stat.h>
 5 #include <sys/time.h>
 6 #include <sys/types.h>
 7 #include <sys/select.h>
 8 #include <fcntl.h>
 9 int main(int argc, const char *argv[])
10 {
11     char name[128];
12     memset(name, 0, 128);
13     sprintf(name, "%d.fifo", getpid());
14     if(mkfifo(name, 0666) == -1)
15     {
16         printf("创建管道失败!!\n");
17         exit(1);
18     }
19     int fd;
20     fd = open(argv[1], O_WRONLY);
21     if(fd == -1)
22     {
23         printf("open error!!\n");
24         exit(1);
25     }
26     char buf[128];
27     memset(buf, 0, 128);
28     sprintf(buf,"on %d\n",getpid());
29     write(fd, buf, strlen(name));
30     int sfd;
31     sfd = open(name, O_RDONLY);
32     if(sfd == -1)
33     {
34         printf("open error!!\n");
35         exit(1);
36     }
37     if(fork() == 0)
38     {
39         if(fork() == 0)
40         {
41             close(fd);
42             while(memset(buf, 0, 128), read(sfd, buf, 128))
43                 printf(" >> %s\n", buf);
44             close(sfd);
45             exit(1);
46         }
47         exit(1);
48     }
49     wait(NULL);
50     close(sfd);
51     while(memset(buf, 0, 128), fgets(buf, 128, stdin) != NULL)
52     {
53         char msg[128];
54         memset(msg, 0, 128);
55         sprintf(msg, "from %d: %s",getpid(), buf);
56         write(fd, msg, strlen(msg));
57     }
58     memset(buf, 0, 128);
59     sprintf(buf, "off %d\n", getpid());
60     write(fd, buf, strlen(buf));
61     close(fd);
62     unlink(name);
63     return 0;
64 }

时间: 2024-10-06 04:58:23

Linux基础——通过select实现简单的服务器与客户端的相关文章

linux 网络编程之最简单的tcp通信客户端

编写一个最为简单的tcp通信客户端.代码如下: #include <iostream> #include <cstring> using namespace std; #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <netinet/in.h> #include <errno.h> int main() { /*创

转:Linux下使用Nginx搭建简单图片服务器

最近经常有人问图片上传怎么做,有哪些方案做比较好,也看到过有关于上传图片的做法,但是都不是最好的,今天再这里简单讲一下Nginx实现上传图片以及图片服务器的大致理念. 如果是个人项目或者企业小项目,仅仅只有十来号人使用的小项目,可以使用如下方案: 用户访问系统,使用上传图片功能,那么图片就上传到你的当前项目所在的tomcat服务器上,在/image下,上传成功后用户可以直接访问 http://ip:port/project/images/xxx.jpg 这样做在用户少的时候是没有问题的 当你的企

Linux基础——ls功能的简单实现

简单的ls实现,首先,我们需要遍历参数目录下的各个文件,再根据文件相应的性质,读取文件的权限,用户组,用户名,大小,最后一次访问的时间,再根据文件名排序后依次显示. 具体的函数声明如下: 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <sys/stat.h> 5 #include <fcntl.h> 6 #include <unistd

linux基础之sudu的简单用法

su: Switch User, 以管理员身份运行某些命令: su -l root -c 'COMMAND' 但是想要限制某个用户只拥有一部分管理员权限,而不是拥有全部权限,这就需要用到sudo sudo: 是可以让某个用户不需要拥有管理员的密码,可以执行管理员的权限 作为管理员可以指派某些用户可以执行某些特定命令,类似suid 配置文件:/etc/sudoers root ALL=(ALL) ALL %wheel ALL=(ALL) ALL %wheel: 运行命令者的身份,user 第一个A

Linux 用libevent实现的简单http服务器

main.c #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <stdlib.h> #include "libev.h" #include <string.h> #include <event2/event.h&

用C++写一个简单的服务器和客户端

我们将创建一个服务器节点add_two_ints_server,它将会收到两个整数,并且返回它们的和.切换目录到之前建立的beginner_tutorials包下: cd ~/catkin_ws/src/beginner_tutorials 编辑src/add_two_ints_server.cpp文件: vim src/add_two_ints_server.cpp 也就是说我们写的客户点也是一个node节点,它的cpp和生成的可执行模块和前面的talker.listener是一样的,只不过他

Python 使用Socket模块编写一个简单的服务器和客户端

任务 Socket套接字开始监听后,使用accept函数来等待客户连接.这个过程在循环中无限循环,服务器处理完和客户端的连接后会再次调用accpet函数,等待下一个连接. 客户端代码 1 import socket 2 s1=socket.socket() 3 s1.bind(("127.0.0.1",2345)) 4 s1.listen(5) 5 while 1: 6 conn,address = s1.accept() 7 print("a new connect fro

python3实现UDP协议的简单服务器和客户端

利用python中的socket模块中的来实现UDP协议,这里写一个简单的服务器和客户端.为了说明网络编程中UDP的应用,这里就不写图形化了,在两台电脑上分别打开UDP的客户端和服务端就可以了. UDP:用户数据报协议,是一个面向无连接的协议.采用该协议不需要两个应用程序先建立连接.UDP协议不提供差错恢复,不能提供数据重传,因此该协议传输数据安全性差. 客户端 python3只能收发二进制数据,需要显式转码 from socket import * host = '192.168.48.128

[Z] linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO

原文链接:http://blog.csdn.net/colzer/article/details/8169075 IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file descriptor(fd,文件描述符).而对一个socket的读写也会有相应的描述符,称为socketfd(socket描述符).描述符就是一个数字,指向内核中一个结构体(文件路径,数据