利用select单线程点对点聊天
select的优点与使用方法
select用单线程的方法遍历所有待读写的I/O接口, 当有接口可用时就会返回. select可设置电脑阻塞或非阻塞.
特别注意: 每次select前都要重新初始化集合和相关的时间结构
使用的基本过程:
//创建要读写的集合,所有的读接口放一个集合,所有的写接口放另一个集合
fd_set fileset1;
fd_set fileset2;
//初始化该集合
FD_ZERO(&fileset1);
FD_ZERO(&fileset2);
//向集合中添加要监听的接口
FD_SET(fd1,&fileset1);
FD_SET(fd2,&fileset1);
...
//开始监听
int ret=select(maxfd+1,&fileset1,&fileset2,NULL,NULL);
//返回后开始处理
switch(ret){
case -1:
if(errno == EINTR)
continue;
err_quit("select");
case 0:
printf("time out\n");
continue;
default:
if(FD_ISSET(fd1,&fileset))
do_service1();
if(FD_ISSET(fd2,&fileset))
do_service2();
if(FD_ISSET(...)
break;
}
实例
只写了server端的,client端差不多
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define MAX(a,b) a>b?a:b;
void err_quit(const char *s){
perror(s);
exit(1);
}
void handler(int signo){
printf("program terminated\n");
exit(0);
}
ssize_t readn(int fd,void *buff,size_t count){
char *buffp;
ssize_t nread;
size_t nleft;
buffp=(char *)buff;
nleft=count;
while(nleft > 0){
if((nread = read(fd,buffp,nleft)) < 0){
if(errno == EINTR)
continue;
else
return -1;
}else if(nread == 0)
break;
nleft -= nread;
buffp += nread;
}
return count-nleft;
}
ssize_t writen(int fd,const void *buff,size_t n){
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr=buff;
nleft=n;
while(nleft > 0){
if((nwritten=write(fd,ptr,nleft)) < 0){
if(nwritten < 0 && errno == EINTR)
continue;
else
return -1;
}else if(nwritten == 0)
break;
nleft -= nwritten;
ptr += nwritten;
}
return n-nleft;
}
ssize_t recv_peek(int fd,void *buf,size_t len){
ssize_t ret;
while(1){
ret=recv(fd,buf,len,MSG_PEEK);
if(ret == -1 && errno == EINTR)
continue;
return ret;
}
}
ssize_t readline(int fd,void *buf,size_t maxline){
ssize_t ret;
size_t nread;
size_t nleft;
char *bufp;
bufp=buf;
nleft=maxline;
while(1){
ret=recv_peek(fd,buf,nleft);
if(ret < 0)
return ret;
else if(ret == 0)
return ret;
nread=ret;
int i;
for(i=0;i<nread;i++){
if(bufp[i] == '\n'){
ret=readn(fd,bufp,i+1);
if(ret != i+1)
err_quit("readn");
return ret;
}
}
if(nread > nleft)
err_quit("readn");
nleft -= nread;
ret=readn(fd,bufp,nread);
if(ret != nread)
err_quit("readn");
bufp += nread;
}
return -1;
}
void recv_service(int fd){
char buf[1024]={0};
int ret=readline(fd,buf,sizeof(buf));
if(ret == -1)
err_quit("read");
else if(ret == 0){
printf("peer closed\n");
exit(0);
}
fputs(buf,stdout);
}
void send_service(int fd){
char buf[1024];
if(fgets(buf,sizeof(buf),stdin) != NULL){
writen(fd,buf,strlen(buf));
}
}
int main(int argc,char *argv[]){
int sockfd,connfd;
socklen_t len;
struct sockaddr_in addr,client;
if((sockfd=socket(PF_INET,SOCK_STREAM,0)) < 0)
err_quit("sockfd");
bzero(&addr,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY);
addr.sin_port=htons(5566);
int on=1;
if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) <0)
err_quit("setsockopt");
if(bind(sockfd,(struct sockaddr *)&addr,sizeof(addr))<0)
err_quit("bind");
if(listen(sockfd,10)<0)
err_quit("listen");
len=sizeof(client);
connfd=accept(sockfd,(struct sockaddr *)&client,&len);
if(connfd < 0)
err_quit("accept");
struct sockaddr_in peeraddr;
socklen_t lenth=sizeof(peeraddr);
if(getpeername(connfd,(struct sockaddr *)&peeraddr,&lenth) < 0)
err_quit("getpeername");
printf("peer addr=%s,peer port=%d\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port));
char buf[1024];
bzero(buf,sizeof(buf));
fd_set fileset;
while(1){
FD_ZERO(&fileset);
FD_SET(STDIN_FILENO,&fileset);
FD_SET(connfd,&fileset);
int maxfd=MAX(STDIN_FILENO,connfd);
int ret=select(maxfd+1,&fileset,NULL,NULL,NULL);
switch(ret){
case -1:
if(errno == EINTR)
continue;
err_quit("select");
case 0:
printf("time out\n");
continue;
default:
if(FD_ISSET(connfd,&fileset))
recv_service(connfd);
if(FD_ISSET(STDIN_FILENO,&fileset))
send_service(connfd);
break;
}
}
exit(0);
}
利用select单线程点对点聊天的更多相关文章
- 利用select实现伪并发的socket
使用socket模块可以实现程序之间的通信,但是server在同一时刻只能和一个客户端进行通信,如果要实现一个server端可以和多个客户端进行通信可以使用 1.多线程 2.多进程 3.select ...
- Activemq mqtt 点对点聊天实现(转载)
我这想到一个点对点聊天的方法,不用没割人都建立一个topic了,思路还是自定义一个分发策略,具体如下: 1. 建立一个topic,所有人都用匹配订阅的方式订阅以该topic为头的topic,例如:所 ...
- Linux 网络编程详解三(p2p点对点聊天)
//p2p点对点聊天多进程版--服务器(信号的使用) #include <stdio.h> #include <stdlib.h> #include <string.h& ...
- sql判断以逗号分隔的字符串中是否包含某个字符串--------MYSQL中利用select查询某字段中包含以逗号分隔的字符串的记录方法
sql判断以逗号分隔的字符串中是否包含某个字符串---------------https://blog.csdn.net/wttykj/article/details/78520933 MYSQL中利 ...
- 老雷socket编程之PHP利用socket扩展实现聊天服务
老雷socket编程之PHP利用socket扩展实现聊天服务 socket聊天服务原理 PHP有两个socket的扩展 sockets和streamssockets socket_create(AF_ ...
- 利用select/poll监听多个设备详解
如果一个应用程序去处理多个设备,例如应用程序读取网路数据,按键,串口,一般能想到的有三种方法: 方法1:串行+阻塞的方式读取:while(1) { read(标准输入);read(网络);}缺点:每当 ...
- java select单线程 服务器
package com.Select; /** *select单线程 服务器 **/ import java.io.IOException; import java.net.InetSocketAdd ...
- 基于select的python聊天室程序
python网络编程具体参考<python select网络编程详细介绍>. 在python中,select函数是一个对底层操作系统的直接访问的接口.它用来监控sockets.files和 ...
- 利用scrollintoview方法模拟聊天室收到新消息
这段时间再写一个聊天的功能,基本的原理已经通了,剩下的就是细化功能和实现了.原理通了不代表就能解决了这个问题,今天就遇到了一个小问题,就是在接收到新的消息以后,最新的消息不能显示在消息区域,而是跑到了 ...
随机推荐
- 2015 GDUT校赛
周末打了个GDUT的校赛,也是作为SCAU的一场个人排位. 比赛中竟然卡了个特判,1个半钟就切了5条了,然后一直卡. 还有其他两条可以做的题也没法做了,性格太执着对ACM来说也是错呀. 讲回正题 . ...
- Laya2.0的转变
之前一直用Laya1.x+TypeScript了,最近项目开始使用Laya2.0+AS3了 总结一下需要注意的一些事项,算是2种开发模式的区别与过渡吧 1.AS类的访问标识 必须是public,不写会 ...
- Codeforces 208E. Blood Cousins
传送门 题目大意: 小C喜欢研究族谱,这一天小C拿到了一整张族谱. 小C先要定义一下k-祖先. x的1-祖先指的是x的父亲 x的k-祖先指的是x的(k-1)-祖先的父亲 小C接下来要定义k-兄弟 x的 ...
- k8s阅读笔记2-k8s架构
前言 阅读地址 https://rootsongjc.gitbooks.io/kubernetes-handbook/content/concepts/ 架构 架构图说明: master 指服务端 1 ...
- Sass--混合宏--声明宏
如果你的整个网站中有几处小样式类似,比如颜色,字体等,在 Sass 可以使用变量来统一处理,那么这种选择还是不错的.但当你的样式变得越来越复杂,需要重复使用大段的样式时,使用变量就无法达到我们目了.这 ...
- javascript 浏览器定位
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- HTML5 表单提交实例
html <!DOCTYPE html> <html> <head> <title>表单</title> <meta charset= ...
- centos7安装nginx并配置web前端环境。
1.安装nginx -sudo yum install nginx 2.启动nginx - systemctl start nginx 3.修改nginx路径配置,/etc/nginx/nginx.c ...
- 排查Java高CPU占用原因
近期java应用,CPU使用率一直很高,经常达到100%,通过以下步骤完美解决,分享一下. 方法一: 转载:http://www.linuxhot.com/java-cpu-used-high.htm ...
- 英语单词custom
custom 来源——xshell快捷键 翻译 n. 习惯,惯例:风俗:海关,关税:经常光顾:[总称](经常性的)顾客 adj. (衣服等)定做的,定制的 高中 | 初中 词源 英语单词custom含 ...