用select实现1对多的网络通信,多线程实现,且可以实现退出,相互间对话消息不受干扰
2014-12-22 11:04
399 查看
/*用select实现多线程并行网络通信,1对多通信*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#define portnumber 3333
#define MAXCLIENTNUM 5
static int totalNum = 0;
static sem_t sem; //信号量
void Process(void *arg)
{
printf("processstarting... Thread ID: %d\n", pthread_self());
fd_set readfd;
int nbytes;
char buffer[1024];
int fd = (int) arg;
while(1)
{
FD_ZERO(&readfd);
FD_SET(fd,&readfd);
FD_SET(0,&readfd);
int i,maxfd = fd + 1;
int r= select(maxfd, &readfd, NULL, NULL, NULL);
if(r>= 0)
{
//服务器接收消息
if(FD_ISSET(fd, &readfd))
{
sem_wait(&sem); //获取信号量
if((nbytes = read(fd, buffer, 1024)) == -1)
{
fprintf(stderr,"ReadError:%s\n",strerror(errno));
exit(1);
}
if(nbytes == 0)
{
printf("client%d has exit!\n", maxfd);
sem_post(&sem); //一定要释放信号量
break;
}
buffer[nbytes]='\0';
printf("client%d say: %s\n", maxfd, buffer);
sem_post(&sem);//释放信号量
sleep(1);
}
//服务器发送消息
if(FD_ISSET(0,&readfd)) //从服务器终端输入数据
{
sem_wait(&sem);//获取信号量
memset(buffer,0, sizeof(buffer));
fgets(buffer,1024, stdin);
if(strncmp(buffer,"quit", 4) == 0)
{
printf("areyou sure to quit: yes or no \n");
memset(buffer, 0, sizeof(buffer));
fgets(buffer,1024, stdin);
if(strncmp(buffer,"yes", 3)== 0)
{
write(fd, "server has quit",15);
sleep(3); //睡眠3秒,保证把要退出的信号告诉客户端
FD_CLR(fd,&readfd);
close(fd);
exit(0);
}
else
continue;
}
write(fd,buffer,strlen(buffer));
sem_post(&sem);//释放信号量
sleep(1);
}
}
else
{
printf("select error!\n");
exit(-1);
}
sleep(1);//实现一对多通信
}
FD_CLR(fd,&readfd);
close(fd);
pthread_exit(NULL);
/* 循环下一个 */
}
int main(int argc, char *argv[])
{
int sockfd,new_fd;
struct sockaddr_inserver_addr;
struct sockaddr_inclient_addr;
int sin_size;
/* 服务器端开始建立sockfd描述符 */
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
fprintf(stderr,"Socketerror:%s\n\a",strerror(errno));
exit(1);
}
printf("Socketsuccess.....\n");
/* 服务器端填充 sockaddr结构 */
bzero(&server_addr,sizeof(structsockaddr_in)); //
初始化,置0
server_addr.sin_family=AF_INET; // Internet
server_addr.sin_addr.s_addr=htonl(INADDR_ANY); // (将本机器上的long数据转化为网络上的long数据)和任何主机通信
//INADDR_ANY 表示可以接收任意IP地址的数据,即绑定到所有的IP
//server_addr.sin_addr.s_addr=inet_addr("192.168.1.1"); //用于绑定到一个固定IP,inet_addr用于把数字加格式的ip转化为整形ip
server_addr.sin_port=htons(portnumber); // (将本机器上的short数据转化为网络上的short数据)端口号
/* 捆绑sockfd描述符到IP地址
*/
printf("startbindding.....\n");
if(bind(sockfd,(structsockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"Binderror:%s\n\a",strerror(errno));
exit(1);
}
/* 设置允许连接的最大客户端数 */
printf("startlistening.....\n");
printf("The maxnumber of client to allow to connect with server is:%d.....\n",MAXCLIENTNUM);
if(listen(sockfd,MAXCLIENTNUM)==-1)
{
fprintf(stderr,"Listenerror:%s\n\a",strerror(errno));
exit(1);
}
printf("serverworking.....\n");
sem_init(&sem,0, 1); //初始化信号量
while(1)
{
sin_size=sizeof(structsockaddr_in);
if((new_fd=accept(sockfd,(structsockaddr *)(&client_addr),&sin_size))==-1)
{
fprintf(stderr,"Accepterror:%s\n\a",strerror(errno));
exit(1);
}
fprintf(stderr,"Server get connection from %s\n", inet_ntoa(client_addr.sin_addr));//
将网络地址转换成.字符串
//创建工作者线程
pthread_tpwork;
interr = pthread_create(&pwork, NULL, (void*)Process, (void*)new_fd);
if(err!= 0)
{
printf("pthread_createerror!\n");
exit(0);
}
}
/* 结束通讯 */
close(sockfd);
exit(0);
}
/*客户端程序*/
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#include<netdb.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#defineportnumber 3333
intmain(int argc, char *argv[])
{
int sockfd;
char buffer[1024];
struct sockaddr_in server_addr;
struct hostent *host;
/* 使用hostname查询host 名字 */
if(argc!=2)
{
fprintf(stderr,"Usage:%shostname \a\n",argv[0]);
exit(1);
}
if((host=gethostbyname(argv[1]))==NULL)
{
fprintf(stderr,"Gethostnameerror\n");
exit(1);
}
/* 客户程序开始建立sockfd描述符 */
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)//
{
fprintf(stderr,"SocketError:%s\a\n",strerror(errno));
exit(1);
}
/* 客户程序填充服务端的资料*/
bzero(&server_addr,sizeof(server_addr));// 初始化,置0
server_addr.sin_family=AF_INET; // IPV4
server_addr.sin_port=htons(portnumber); // (将本机器上的short数据转化为网络上的short数据)端口号
server_addr.sin_addr=*((struct in_addr*)host->h_addr); // IP地址
/* 客户程序发起连接请求*/
if(connect(sockfd,(struct sockaddr*)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"ConnectError:%s\a\n",strerror(errno));
exit(1);
}
printf("Start totalking...\n");
while(1)
{
fd_set readfd;
FD_ZERO(&readfd);
FD_SET(sockfd,&readfd);
FD_SET(0,&readfd); //把标准输入描述符加入描述符集
int maxfd = ((0 >sockfd) ? 0 : sockfd);
fd_set tmpfd = readfd;
/* 发送数据 */
int r = select(maxfd + 1,&readfd, NULL, NULL, NULL);
if(r < 0)
{
printf("selecterror!\n");
exit(0);
}
else if(r == 0)
{
printf("Waitingserver reply!\n");
continue;
}
else
{
//客户端输入数据
if(FD_ISSET(0,&readfd))
{
memset(buffer,0, sizeof(buffer));
fgets(buffer,1024, stdin);
if(strncmp(buffer,"quit", 4) == 0)
{
write(sockfd,"I will quit", 20);
printf("areyou sure to quit: yes or no \n");
memset(buffer,0, sizeof(buffer));
fgets(buffer,1024, stdin);
if(strncmp(buffer,"yes", 3)== 0)
{
write(sockfd,"BYE BYE!^ ^", 15);
sleep(3);
FD_CLR(sockfd,&readfd);
close(sockfd);
exit(0);
}
else
continue;
}
/*连接成功了 */
write(sockfd,buffer,strlen(buffer));
}
//接收从服务器发来的数据
if(FD_ISSET(sockfd,&readfd))
{
intnbytes;
memset(buffer,0, sizeof(buffer));
if((nbytes= read(sockfd, buffer, 1024)) == -1)
{
fprintf(stderr,"ReadError:%s\n",strerror(errno));
exit(1);
}
if(nbytes== 0)
{
printf("serverhas exit!\n");
close(sockfd);
exit(0);
}
buffer[nbytes]='\0';
printf("serversay: %s\n", buffer);
}
}
}
/* 结束通讯*/
close(sockfd);
exit(0);
}
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#define portnumber 3333
#define MAXCLIENTNUM 5
static int totalNum = 0;
static sem_t sem; //信号量
void Process(void *arg)
{
printf("processstarting... Thread ID: %d\n", pthread_self());
fd_set readfd;
int nbytes;
char buffer[1024];
int fd = (int) arg;
while(1)
{
FD_ZERO(&readfd);
FD_SET(fd,&readfd);
FD_SET(0,&readfd);
int i,maxfd = fd + 1;
int r= select(maxfd, &readfd, NULL, NULL, NULL);
if(r>= 0)
{
//服务器接收消息
if(FD_ISSET(fd, &readfd))
{
sem_wait(&sem); //获取信号量
if((nbytes = read(fd, buffer, 1024)) == -1)
{
fprintf(stderr,"ReadError:%s\n",strerror(errno));
exit(1);
}
if(nbytes == 0)
{
printf("client%d has exit!\n", maxfd);
sem_post(&sem); //一定要释放信号量
break;
}
buffer[nbytes]='\0';
printf("client%d say: %s\n", maxfd, buffer);
sem_post(&sem);//释放信号量
sleep(1);
}
//服务器发送消息
if(FD_ISSET(0,&readfd)) //从服务器终端输入数据
{
sem_wait(&sem);//获取信号量
memset(buffer,0, sizeof(buffer));
fgets(buffer,1024, stdin);
if(strncmp(buffer,"quit", 4) == 0)
{
printf("areyou sure to quit: yes or no \n");
memset(buffer, 0, sizeof(buffer));
fgets(buffer,1024, stdin);
if(strncmp(buffer,"yes", 3)== 0)
{
write(fd, "server has quit",15);
sleep(3); //睡眠3秒,保证把要退出的信号告诉客户端
FD_CLR(fd,&readfd);
close(fd);
exit(0);
}
else
continue;
}
write(fd,buffer,strlen(buffer));
sem_post(&sem);//释放信号量
sleep(1);
}
}
else
{
printf("select error!\n");
exit(-1);
}
sleep(1);//实现一对多通信
}
FD_CLR(fd,&readfd);
close(fd);
pthread_exit(NULL);
/* 循环下一个 */
}
int main(int argc, char *argv[])
{
int sockfd,new_fd;
struct sockaddr_inserver_addr;
struct sockaddr_inclient_addr;
int sin_size;
/* 服务器端开始建立sockfd描述符 */
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
fprintf(stderr,"Socketerror:%s\n\a",strerror(errno));
exit(1);
}
printf("Socketsuccess.....\n");
/* 服务器端填充 sockaddr结构 */
bzero(&server_addr,sizeof(structsockaddr_in)); //
初始化,置0
server_addr.sin_family=AF_INET; // Internet
server_addr.sin_addr.s_addr=htonl(INADDR_ANY); // (将本机器上的long数据转化为网络上的long数据)和任何主机通信
//INADDR_ANY 表示可以接收任意IP地址的数据,即绑定到所有的IP
//server_addr.sin_addr.s_addr=inet_addr("192.168.1.1"); //用于绑定到一个固定IP,inet_addr用于把数字加格式的ip转化为整形ip
server_addr.sin_port=htons(portnumber); // (将本机器上的short数据转化为网络上的short数据)端口号
/* 捆绑sockfd描述符到IP地址
*/
printf("startbindding.....\n");
if(bind(sockfd,(structsockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"Binderror:%s\n\a",strerror(errno));
exit(1);
}
/* 设置允许连接的最大客户端数 */
printf("startlistening.....\n");
printf("The maxnumber of client to allow to connect with server is:%d.....\n",MAXCLIENTNUM);
if(listen(sockfd,MAXCLIENTNUM)==-1)
{
fprintf(stderr,"Listenerror:%s\n\a",strerror(errno));
exit(1);
}
printf("serverworking.....\n");
sem_init(&sem,0, 1); //初始化信号量
while(1)
{
sin_size=sizeof(structsockaddr_in);
if((new_fd=accept(sockfd,(structsockaddr *)(&client_addr),&sin_size))==-1)
{
fprintf(stderr,"Accepterror:%s\n\a",strerror(errno));
exit(1);
}
fprintf(stderr,"Server get connection from %s\n", inet_ntoa(client_addr.sin_addr));//
将网络地址转换成.字符串
//创建工作者线程
pthread_tpwork;
interr = pthread_create(&pwork, NULL, (void*)Process, (void*)new_fd);
if(err!= 0)
{
printf("pthread_createerror!\n");
exit(0);
}
}
/* 结束通讯 */
close(sockfd);
exit(0);
}
/*客户端程序*/
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#include<netdb.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#defineportnumber 3333
intmain(int argc, char *argv[])
{
int sockfd;
char buffer[1024];
struct sockaddr_in server_addr;
struct hostent *host;
/* 使用hostname查询host 名字 */
if(argc!=2)
{
fprintf(stderr,"Usage:%shostname \a\n",argv[0]);
exit(1);
}
if((host=gethostbyname(argv[1]))==NULL)
{
fprintf(stderr,"Gethostnameerror\n");
exit(1);
}
/* 客户程序开始建立sockfd描述符 */
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)//
{
fprintf(stderr,"SocketError:%s\a\n",strerror(errno));
exit(1);
}
/* 客户程序填充服务端的资料*/
bzero(&server_addr,sizeof(server_addr));// 初始化,置0
server_addr.sin_family=AF_INET; // IPV4
server_addr.sin_port=htons(portnumber); // (将本机器上的short数据转化为网络上的short数据)端口号
server_addr.sin_addr=*((struct in_addr*)host->h_addr); // IP地址
/* 客户程序发起连接请求*/
if(connect(sockfd,(struct sockaddr*)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"ConnectError:%s\a\n",strerror(errno));
exit(1);
}
printf("Start totalking...\n");
while(1)
{
fd_set readfd;
FD_ZERO(&readfd);
FD_SET(sockfd,&readfd);
FD_SET(0,&readfd); //把标准输入描述符加入描述符集
int maxfd = ((0 >sockfd) ? 0 : sockfd);
fd_set tmpfd = readfd;
/* 发送数据 */
int r = select(maxfd + 1,&readfd, NULL, NULL, NULL);
if(r < 0)
{
printf("selecterror!\n");
exit(0);
}
else if(r == 0)
{
printf("Waitingserver reply!\n");
continue;
}
else
{
//客户端输入数据
if(FD_ISSET(0,&readfd))
{
memset(buffer,0, sizeof(buffer));
fgets(buffer,1024, stdin);
if(strncmp(buffer,"quit", 4) == 0)
{
write(sockfd,"I will quit", 20);
printf("areyou sure to quit: yes or no \n");
memset(buffer,0, sizeof(buffer));
fgets(buffer,1024, stdin);
if(strncmp(buffer,"yes", 3)== 0)
{
write(sockfd,"BYE BYE!^ ^", 15);
sleep(3);
FD_CLR(sockfd,&readfd);
close(sockfd);
exit(0);
}
else
continue;
}
/*连接成功了 */
write(sockfd,buffer,strlen(buffer));
}
//接收从服务器发来的数据
if(FD_ISSET(sockfd,&readfd))
{
intnbytes;
memset(buffer,0, sizeof(buffer));
if((nbytes= read(sockfd, buffer, 1024)) == -1)
{
fprintf(stderr,"ReadError:%s\n",strerror(errno));
exit(1);
}
if(nbytes== 0)
{
printf("serverhas exit!\n");
close(sockfd);
exit(0);
}
buffer[nbytes]='\0';
printf("serversay: %s\n", buffer);
}
}
}
/* 结束通讯*/
close(sockfd);
exit(0);
}
相关文章推荐
- 第01天多线程网络:(16):GCD实现线程间通信
- 多线程进行网络通信是否可以达到更快的速度?
- Linux下网络socket编程——实现服务器(select)与多个客户端通信
- 利用多线程实现网络通信
- 第02天多线程网络:(14):NSOperation实现线程间通信
- Android移动开发-使用多线程进行网络聊天室通信的实现
- 实现了UI的简单群聊(java的IO流和多线程,网络通信)
- 第01天多线程网络:(11):NSThread实现线程间通信
- 网络多线程-NSThread实现线程间通信
- WCF服务通过TCP实时监控客户端状态,并可以向客户端广播推送消息,实现双向通信
- 多线程和网络通信实现的简单多线程上传
- PostThreadMessage实现多线程间消息通信
- 通过网络编程、文件IO、多线程,实现客户端和服务端对话。
- Android 网络:基于TCP协议通信,多线程,实现简单的C/S聊天室
- Java基于多线程的网络通信实现服务器计算正方形面积
- Linux Socket 网络编程 基于GTK+ 的多线程实现的局域网通信软件
- 多线程和网络通信实现的简单文件下载
- 学习笔记:delphi实现网络通信之select模型
- Linux Socket 网络编程 基于GTK+ 的多线程实现的局域网通信软件
- 利用MFC的Csocket类实现网络通信1