(三)TCP用select函数处理多个客户端连接(非阻塞模式)

这个程序,客户端们通过服务器进行群聊。
主要讲讲两点:1.怎么弄非阻塞模式 。 2.select的粗略讲解(心急的可以跳过,直接看后面代码)


首先,看看这个程序服务端设计的基本逻辑,其实非常简单,就在一个while(1)循环里面不停地轮询 accept 和 select函数。
有人可能问,accept不是会阻塞,直到有客户端连接进来的吗?
其实当你的socket套接字设置成非阻塞模式,那么accept也不会阻塞。

1.那怎么弄非阻塞呢?
这就涉及到 fcntl函数。fcntl能改变文件的属性。看看他的原型:int fcntl(int fd, int cmd);失败返回-1(当然这个函数还有很多用途,但这里只谈谈他如何实现非阻塞)
三行代码:
long val = fcntl(sockfd,F_GETFL); //把sockfd套接字的属性拿出来给val
val|=O_NONBLOCK;		  //把非阻塞的属性O_NONBLOCK加进去,用或运算
fcntl(sockfd,F_SETFL,val);	  //再把做好的属性val,再加到sockfd中去
这时候 把sockfd 作为参数给 accept,accept就不会再阻塞。


2.select()函数:select函数能够同时监听多个文件描述符,若其中一个或多个文件描述符有反应(读或写),select就会返回。
原型: int select(nfds, readfds, writefds, errfds, timeout)  

fd_set *readfds, *writefds, *errfds;   //第2,3,4个参数都是文件描述符集,对Socket编程比较有用的是 readfds。  
struct timeval *timeout;               //控制select()如何返回,是非阻塞,还是阻塞一定时间返回,还是直接有文件描述符有响应才返回。

函数参数:
    1.nfs:最大的文件描述符+1,这个不能错,若不能确定,写一个算法找出来,下面提供的代码有
    2.可读文件描述符集。什么意思呢,就是这个集中的文件描述符随时可能给服务器写数据,那作为服务器,就要监测这些文件描述符,若不关心可读,填NULL。
    3.可写文件描述符集。这里不用到,就不说了。若不关心,可填NULL
    4.异常文件描述符集。若不关心,可填NULL。
    5.时间控制结构体。这个结构体里面有2个成员。一个代表秒,一个代表毫秒。两个都设成0表示select将会非阻塞返回。

对此,还有一些列的宏提供给select用:
     1.FD_SET();  用来把文件描述符加到文件描述符集中
     2.FD_ZERO(); 清空文件描述符集中的所有描述符
     3.FD_ISSET();判断某个文件描述符有没有响应。
     注意:select每返回一次后,都要重新清空文件描述符集,和重新把文件描述符加到文件描述符集中。

下面给出服务端的代码:
//TCP服务端
#include"myhead.h"

struct client_list
{
	int sock;
	struct client_list *next;
};


struct client_list *head = NULL;

struct client_list *init_list(struct client_list*head)
{
	head = malloc(sizeof(struct client_list));
	head->sock = -1;
	head->next = NULL;
	return head;
}

//新的客户端加到客户端队列中
int add_sock(struct client_list*head,int new_sock)
{
	struct client_list *p = head;
	struct client_list *new_node = malloc(sizeof(struct client_list));
	new_node->sock = new_sock;
	new_node->next = NULL;

	while(p->next!=NULL)
	{
		p = p->next;
	}
	p->next = new_node;
	return 0;
}

//找出最大的文件描述符
int find_max(struct client_list*head)
{
	struct client_list *p = head->next;
	if(p==NULL)
		return 0;
	int max_sd = p->sock;
	for(p;p!=NULL;p=p->next)
	{
		if(max_sd < p->sock)
			max_sd = p->sock;
	}
	return max_sd;
}

//信息转发给其他客户端
int write_to_client(struct client_list*head,char *wbuf,int size)
{
	struct client_list *p=head;
	for(p=head->next;p!=NULL;p=p->next)
	{
		write(p->sock,wbuf,size);
	}
	return 0;
}

//当有新的客户端作为新的文件描述符加进来时,显示客户端列表中的所有客户端文件描述符
void show_client_list(struct client_list*head)
{
	struct client_list *p = head;
	if(p->next == NULL)
	{
		printf("IS A EMPTY LIST!\n");
		return ;
	}
	else
	{
		puts("client_list is :");
		for(p =head->next; p!=NULL;p = p->next)
		{
			printf("%d ",p->sock);
		}
		printf("\n");
	}
}
//取消退出客户端的结点。
int del_node(struct client_list*head,int sock)
{
	struct client_list *p = head->next;
	struct client_list *q = head;
	while(p!=NULL)
	{
		if(p->sock == sock)
		{
			q->next = p->next;
			free(p);
			p = NULL;
		}
		else
		{
			p = p->next;
			q = q->next;
		}
	}
	return 0;
}

int main(int argc, char const *argv[])
{
	char rbuf[50]={0};
	char wbuf[50]={0};

	int sockfd,size,on=1;
	int new_sock;
	int max_sd;
	struct client_list *pos;
	struct timeval timeout = {0,0};  //设置select为非阻塞返回
	fd_set fdset;
	long val;

	head = init_list(head);   //初始化客户端链表。
	pos = head;

	struct sockaddr_in saddr;
	struct sockaddr_in caddr;
	size = sizeof(struct sockaddr_in);
	bzero(&saddr,size);

	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(8888);
	saddr.sin_addr.s_addr = htonl(INADDR_ANY);

	sockfd = socket(AF_INET,SOCK_STREAM,0);
	setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));//设置socket套接字为复用,不设也可以
	
	//把sockfd设置为非阻塞
	val = fcntl(sockfd,F_GETFL);
	val|=O_NONBLOCK;
	fcntl(sockfd,F_SETFL,val);

	bind(sockfd,(struct sockaddr*)&saddr,size);
	listen(sockfd,10);
	while(1)
	{
		new_sock = accept(sockfd,(struct sockaddr*)&caddr,&size);//循环接受新连接的客户端
		if (new_sock!= -1)
		{
			puts("new node come!\n");
			printf("new_sock = %d\n",new_sock);
			add_sock(head,new_sock);

			show_client_list(head);
		}

		max_sd = find_max(head);     //从客户端队列中,找出最大的文件描述符
		FD_ZERO(&fdset);             //清空文件描述符集
		pos = head;
		//把每个套接字加入到集合中
		if(pos->next != NULL)   //若套接字列表不是空    
		{
			for(pos=head->next;pos!=NULL;pos=pos->next)
			{
				FD_SET(pos->sock,&fdset);
			}
		}

		select(max_sd+1,&fdset,NULL,NULL,&timeout); //等待描述符

		for(pos=head->next;pos!=NULL;pos = pos->next) //检查哪个套接字有响应
		{
			if(FD_ISSET(pos->sock,&fdset))           //判断pos->sock这个文件描述符指向的客户端有没有数据写过来
			{
				bzero(rbuf,50);
				read(pos->sock,rbuf,50);
				printf("%s\n",rbuf);
				if(strcmp(rbuf,"quit")==0)  //若客户端发来的信息为quit,则取消这个客户端的结点。
				{
					del_node(head,pos->sock);	
				}
				write_to_client(head,rbuf,50);     //把写过来的信息转发给队列中的其他客户端。		

			}
		}
	}
	return 0;
}



客户端代码:
//客户端
#include"myhead.h"

int main(int argc, char const *argv[])
{
	int sockfd;
	char rbuf[50]={0};
	char wbuf[50]={0};
	char ipbuf[50]={0};
	int port;
	int max_sd;

	int size,on=1;
	int ret;
	fd_set fdset;
	struct sockaddr_in saddr;
	size = sizeof(struct sockaddr_in);

	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(8888);
	saddr.sin_addr.s_addr = inet_addr("192.168.152.128");

	sockfd = socket(AF_INET,SOCK_STREAM,0);
	setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));

	ret = connect(sockfd,(struct sockaddr*)&saddr,size);
	if(ret ==0)
	{
		printf("connect sucess\n");
		inet_ntop(AF_INET,(void*)&saddr.sin_addr.s_addr,ipbuf,50);
		port = ntohs(saddr.sin_port);
		printf("ip:%s,port:%d\n",ipbuf,port);
	}
	else if(ret == -1)
	{
		printf("failed to connect\n");
		return -1;
	}
	
	while(1)
	{
		FD_ZERO(&fdset);
		FD_SET(sockfd,&fdset); //把监测服务端的描述符集放到集合中
		FD_SET(STDIN_FILENO,&fdset); //STDIN_FILENO这个文件描述符用于监测标准输入(键盘)
		max_sd = sockfd>STDIN_FILENO?sockfd:STDIN_FILENO;
		select(max_sd+1,&fdset,NULL,NULL,NULL); //这里的select是设置为一直阻塞到有文件描述符发生响应

		if(FD_ISSET(sockfd,&fdset)) //判断是否服务端有数据发过来
		{
			bzero(rbuf,50);
			read(sockfd,rbuf,50);
			printf("%s\n",rbuf);
		}
		if(FD_ISSET(STDIN_FILENO,&fdset))  //判断键盘是否有数据传过来
		{
			bzero(wbuf,50);
			scanf("%s",wbuf);
			write(sockfd,wbuf,50);         //把键盘传过来的数据发给服务端
			if(strcmp(wbuf,"quit")==0)    //若键盘过来的数据为quit,则关闭这个客户端
			{
				printf("quit!\n");
				return 0;
			}
		}
	}
	return 0;
}


  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《Windows Sockets网络编程》是WindowsSockets网络编程领域公认的经典著作,由Windows Sockets2.0规范解释小组负责人亲自执笔,权威性毋庸置疑。它结合大量示例,对WindowsSockets规范进行了深刻地解读,系统讲解了WindowsSockets网络编程及其相关的概念、原理、主要命令、操作模式,以及开发技巧和可能的陷阱,从程序员的角度给出了大量的建议和最佳实践,是学习WindowsSockets网络编程不可多得的参考书。   全书分为部分:第一部分(第1~6章),提供了翔实的背景知识和框架方面的概念,借助于此框架,读者可理解WinSock的具体细节,包括WindowsSockets概述、OSI网络参考模型、TCP/IP协议簇中的协议和可用的服务、WinSock网络应用程序的框架及其工作机制、WinSock的种操作模式、socket通信机制等;第二部分(第7~12章),以FTP客户端实例为基础介绍了函数实例库,还介绍了客户端程序、服务器程序和DLL中间构件及它们的相应函数,并涵盖socket命令和选项及移植BSDSockets相关事项等;第部分(第13~17章),介绍了应用程序调试技术和工具,针对应用编程中的陷阱的建议和措施,WinSockAPI的多种操作系统平台,WinSock规范的可选功能和WinSock规范2.0中的所有新功能。 译者序 序 前言 第1章 Windows Sockets概述 1.1 什么是Windows Sockets 1.2 Windows Sockets的发展历史 1.3 Windows Sockets的优势 1.3.1 Windows Sockets是一个开放的标准 1.3.2 Windows Sockets提供源代码可移植性 1.3.3 Windows Sockets支持动态链接 1.3.4 Windows Sockets的优点 1.4 Windows Sockets的前景 1.5 结论 第2章 Windows Sockets的概念 2.1 OSI网络模型 2.2 WinSock网络模型 2.2.1 信息与数据 2.2.2 应用协议 2.3 WinSock中的OSI层次 2.3.1 应用层 2.3.2 表示层 2.3.3 会话层 2.3.4 传输层 2.3.5 网络层 2.3.6 数据链路层 2.3.7 物理层 2.4 模块化的层次框 2.5 服务和协议 2.6 协议和API 第3章 TCP/IP协议服务 3.1 什么是TCP/IP 3.2 TCP/IP的发展历史 3.3 传输服务 3.3.1 无连接的服务:UDP 3.3.2 面向连接的服务:TCP 3.3.3 传输协议的选择:UDP与TCP的对比 3.4 网络服务 3.4.1 IP服务 3.4.2 ICMP服务 3.5 支持协议和服务 3.5.1 域名服务 3.5.2 地址解析协议 3.5.3 其他支持协议 3.6 TCP/IP的发展前景 第4章 网络应用程序工作机制 4.1 客户端-服务器模型 4.2 网络程序概览 4.3 socket的打开 4.4 socket的命名 4.4.1 sockaddr结构 4.4.2 sockaddr_in结构 4.4.3 端口号 4.4.4 本地IP地址 4.4.5 什么是socket名称 4.4.6 客户端socket名称是可选的 4.5 与另一个socket建立关联 4.5.1 服务器如何准备建立关联 4.5.2 客户端如何发起一个关联 4.5.3 服务器如何完成一个关联 4.6 socket之间的发送与接收 4.6.1 在“已连接的”socket上发送数据 4.6.2 在“无连接的”socket上发送数据 4.6.3 接收数据 4.6.4 socket解复用器中的关联 4.7 socket的关闭 4.7.1 closesocket 4.7.2 shutdown 4.8 客户端服务器概览 第5章 操作模式 5.1 什么是操作模式 5.1.1 不挂机,等待:阻塞 5.1.2 挂机后再拨:非阻塞 5.1.3 请求对方回拨:异步 5.2 阻塞模式 5.2.1 阻塞socket 5.2.2 阻塞函数 5.2.3 伪阻塞的问题 5.2.4 阻塞钩子函数 5.2.5 阻塞情境 5.2.6 撤销阻塞操作 5.2.7 阻塞操作中的超时 5.2.8 无最少接收限制值 5.2.9 代码示例 5.3 非阻塞模式 5.3.1 怎样使socket成为非阻塞的 5.3.2 成功与失败不是绝对的 5.3.3 探询而非阻塞 5.3.4 显式地避让 5.3.5 代码示例 5.4 异步模式 5.4.1 认识异步函数 5.4.2 撤销异步操作 5.4.3 代码示例 5.4.4 AU_T
第一章 概论 .................................................................................................................. 1 1.1 网络的历史................................................................. ...................................... 1 1.2 OSI 模型........................................................................................................... 3 1.3 Internet 体系模型.............................................................................................. 4 1.4 客户/服务器模型............................................................................................... 5 1.4 UNIX 的历史 ................................................................................................... 7 1.4.1 Unix 诞生前的故事 ................................................................................. 7 1.4.2 UNIX 的诞生.......................................................................................... 8 1.4.3 1979 – UNIX 第七版 ............................................................................. 10 1.4.4 UNIX 仅仅是历史吗?............................................................................. 11 1.5 Linux 的发展.................................................................................................. 11 1.5.1 Linux 的发展历史 .................................................................................. 12 1.5.2 什么叫 GNU? ...................................................................................... 12 1.5.3 Linux 的特色 ........................................................................................ 13 1.5.4 硬件需求............................................................................................... 14 1.5.5 Linux 可用的软件 ................................................................................. 14 1.5.6 为什么选择 Linux ? ............................................................................ 15 1.6 Linux 和 Unix 的发展 .................................................................................... 15 第二章 UNIX/Linux 模型...............................................................................................17 2.1 UNIX/Linux 基本结构.......................................................................................17 2.2 输入和输出......................................................................................................19 2.2.1 UNIX/Linux 文件系统简介 ......................................................................19 2.2.2 流和标准 I/O 库......................................................................................20 2.3 进程 ................................................................................................................21 第章 进程控制 ..........................................................................................................22 3.1 进程的建立与运行 ...........................................................................................22 3.1.1 进程的概念 ............................................................................................22 3.1.2 进程的建立 ............................................................................................22 3.1.3 进程的运行 ............................................................................................24 3.1.4 数据和文件描述符的继承 .......................................................................29 3.2 进程的控制操作...............................................................................................31 3.2.1 进程的终止 ............................................................................................31 3.2.2 进程的同步 ............................................................................................32 3.2.3 进程终止的特殊情况 ..............................................................................33 3.2.4 进程控制的实例 .....................................................................................33 3.3 进程的属性......................................................................................................38 3.3.1 进程标识符 ............................................................................................38 3.3.2 进程的组标识符 .....................................................................................39 3.3.3 进程环境................................................................................................40 3.3.4 进程的当前目录 .....................................................................................42 3.3.5 进程的有效标识符..................................................................................43 3.3.6 进程的资源 ............................................................................................44 3.3.7 进程的优先级.........................................................................................45 3.4 守护进程 .........................................................................................................46 3.4.1 简介.......................................................................................................46 3.4.2 守护进程的启动 ............................................................................................46 3.4.3 守护进程的错误输出 ..............................................................................46 3.4.4 守护进程的建立 .....................................................................................48 3.5 本章小结 .........................................................................................................49 第四章 进程间通信.......................................................................................................50 4.1 进程间通信的一些基本概念 .............................................................................50 4.2 信号 ................................................................................................................50 4.2.1 信号的处理 ............................................................................................52 4.2.2 信号与系统调用的关系...........................................................................54 4.2.3 信号的复位 ............................................................................................55 4.2.4 在进程间发送信号..................................................................................56 4.2.5 系统调用 alarm()和 pause()......................................................................58 4.2.6 系统调用 setjmp()和 longjmp().................................................................62 4.3 管道 ................................................................................................................63 4.3.1 用 C 来建立、使用管道 ..........................................................................65 4.3.2 需要注意的问题 .....................................................................................72 4.4 有名管道 .........................................................................................................72 4.4.1 有名管道的创建 .....................................................................................72 4.4.2 有名管道的 I/O 使用...............................................................................73 4.4.3 未提到的关于有名管道的一些注意 .........................................................75 4.5 文件和记录锁定...............................................................................................75 4.5.1 实例程序及其说明..................................................................................75 4.5.2 锁定中的几个概念..................................................................................78 4.5.3 System V 的咨询锁定..............................................................................78 4.5.4 BSD 的咨询式锁定 .................................................................................79 4.5.5 前面两种锁定方式的比较 .......................................................................81 4.5.6 Linux 的其它上锁技术 ............................................................................81 4.6 System V IPC ...................................................................................................84 4.6.1 ipcs 命令 ................................................................................................85 4.6.2 ipcrm 命令..............................................................................................86 4.7 消息队列(Message Queues)...........................................................................86 4.7.1 有关的数据结构 .....................................................................................86 4.7.2 有关的函数 ............................................................................................89 4.7.3 消息队列实例——msgtool,一个交互式的消息队列使用工具 ..................94 4.8 信号量(Semaphores) .........................................................................................97 4.8.1 有关的数据结构 .....................................................................................98 4.8.2 有关的函数 ............................................................................................99 4.8.3 信号量的实例——semtool,交互式的信号量使用工具........................... 103 4.9 共享内存(Shared Memory) .............................................................................. 109 4.9.1 有关的数据结构 ................................................................................... 109 4.9.2 有关的函数 .......................................................................................... 110 4.9.3 共享内存应用举例——shmtool,交互式的共享内存使用工具................... 112 4.9.4 共享内存与信号量的结合使用 .............................................................. 114 第五章 通信协议简介 ................................................................................................. 120 5.1 引言 .............................................................................................................. 120 5.2 XNS(Xerox Network Systems)概述.............................................................. 120 5.2.1 XNS 分层结构...................................................................................... 120 IPX/SPX 协议概述........................................................................................ 122 5.3 5.3.1 网际包交换(IPX) ............................................................................. 122 5.3.2 排序包交换(SPX)............................................................................. 124 5.4 Net BIOS 概述................................................................................................ 124 5.5 Apple Talk 概述 .............................................................................................. 125 5.6 TCP/IP 概述................................................................................................... 126 5.6.1 TCP/IP 结构模型 .................................................................................. 126 5.6.2 Internet 协议(IP)............................................................................... 127 5.6.3 传输控制协议(TCP) ......................................................................... 132 5.6.4 用户数据报文协议................................................................................ 134 5.7 小结 .............................................................................................................. 135 第六章 Berkeley 套接字 ............................................................................................. 136 6.1 引言 ............................................................................................................. 136 6.2 概述 ............................................................................................................. 136 6.2.1 Socket 的历史...................................................................................... 136 6.2.2 Socket 的功能...................................................................................... 136 6.2.3 套接字的种类型............................................................................... 138 6.3 Linux 支配的网络协议................................................................................... 141 6.3.1 什么是 TCP/IP? ................................................................................... 141 6.4 套接字地址................................................................................................... 142 6.4.1 什么是 Socket? .................................................................................. 142 6.4.2 Socket 描述符...................................................................................... 142 6.4.3 一个套接字是怎样在网络上传输数据的?............................................ 143 6.5 套接字的一些基本知识 ................................................................................. 144 6.5.1 基本结构............................................................................................. 144 6.5.2 基本转换函数...................................................................................... 145 6.6 基本套接字调用............................................................................................ 147 6.6.1 socket() 函数....................................................................................... 147 6.6.2 bind() 函数 ......................................................................................... 148 6.6.3 connect()函数 ...................................................................................... 150 6.6.4 listen() 函数........................................................................................ 151 6.6.5 accept()函数 ........................................................................................ 152 6.6.6 send()、recv()函数 ............................................................................... 154 6.6.7 sendto() 和 recvfrom() 函数 ................................................................. 155 6.6.8 close()和 shutdown()函数...................................................................... 156 6.6.9 setsockopt() 和 getsockopt() 函数 ......................................................... 157 6.6.10 getpeername()函数.............................................................................. 157 6.6.11 gethostname()函数.............................................................................. 158 6.7 DNS 的操作.................................................................................................. 158 6.7.1 理解 DNS............................................................................................ 158 6.7.2 和 DNS 有关的函数和结构 .................................................................. 158 6.7.3 DNS 例程............................................................................................ 159 6.8 套接字的 Client/Server 结构实现的例子.......................................................... 160 6.8.1 简单的流服务器 .................................................................................. 161 6.8.2 简单的流式套接字客户端程序 ............................................................. 163 6.8.3 数据报套接字例程(DatagramSockets)............................................... 165 6.9 保留端口 ...................................................................................................... 169 6.9.1 简介.................................................................................................... 169 6.9.2 保留端口............................................................................................. 170 6.10 五种 I/O 模式................................................................................................. 179 6.10.1 阻塞 I/O 模式 .................................................................................... 179 6.10.2 非阻塞模式 I/O.................................................................................. 180 6.10.3 I/O 多路复用 ..................................................................................... 181 6.10.4 信号驱动 I/O 模式 ............................................................................. 182 6.10.5 异步 I/O 模式 .................................................................................... 185 6.10.6 几种 I/O 模式的比较.......................................................................... 186 6.10.7 fcntl()函数 ......................................................................................... 186 6.10.8 套接字选择项 select()函数.................................................................. 187 6.11 带外数据..................................................................................................... 190 6.11.1 TCP 的带外数据 ................................................................................ 190 6.11.2 OOB 传输套接字例程(服务器代码 Server.c) ................................... 193 6.11.3 OOB 传输套接字例程(客户端代码 Client.c).................................... 196 6.11.4 编译例子 ........................................................................................... 199 6.12 使用 Inetd(Internet 超级服务器) ............................................................... 199 6.12.1 简介.................................................................................................. 199 6.12.2 一个简单的 inetd 使用的服务器程序 hello inet service.......................... 199 6.12.3 /etc/services 和 /etc/inetd.conf 文件 ..................................................... 200 6.12.4 一个复杂一些的 inetd 服务器程序 ...................................................... 201 6.12.5 一个更加复杂的 inetd 服务器程序 ...................................................... 203 6.12.6 程序必须遵守的安全性准则............................................................... 205 6.12.7 小结.................................................................................................. 205 6.13 本章总结 .................................................................................................... 205 第七章 网络安全性..................................................................................................... 206 7.1 网络安全简介 ................................................................................................ 206 7.1.1 网络安全的重要性................................................................................ 206 7.1.2 信息系统安全的脆弱性......................................................................... 207 7.2 Linux 网络不安全的因素 ................................................................................ 209 7.3 Linux 程序员安全........................................................................................... 211 7.3.1 系统子程序 .......................................................................................... 212 7.3.2 标准 C 函数库....................................................................................... 214 7.3.3 书写安全的 C 程序................................................................................ 216 7.3.4 SUID/SGID 程序指导准则...................................................................... 217 7.3.5 root 程序的设计.................................................................................... 218 7.4 小结 .............................................................................................................. 219 第八章 Ping 例程 ....................................................................................................... 220 8.1 Ping 命令简介 ................................................................................................ 220 8.2 Ping 的基本原理............................................................................................. 220 8.3 小结 .............................................................................................................. 221 第九章 tftp 例程......................................................................................................... 222 9.1 tftp 协议简介.................................................................................................. 222 9.2 tftp 的使用 ..................................................................................................... 222 9.3 tftp 的原理 ..................................................................................................... 223 9.3 tftp 的基本结构 .............................................................................................. 223 9.4 小节 .............................................................................................................. 225 第十章 远程命令执行 ................................................................................................. 226 10.1 引言 ............................................................................................................ 226 10.2 rcmd 函数和 rshd 服务器............................................................................... 227 10.3 rexec 函数和 rexecd 服务器........................................................................... 233 第十一章 远程注册..................................................................................................... 235 11.1 简介............................................................................................................. 235 11.2 终端行律和伪终端........................................................................................ 235 11.3 终端方式字和控制终端................................................................................. 239 11.4 rlogin 概述.................................................................................................... 242 11.5 窗口环境...................................................................................................... 242 11.6 流控制与伪终端方式字................................................................................. 243 11.7 rlogin 客户程序............................................................................................. 245 11.8 rlogin 服务器 ................................................................................................ 246 第十二章 远程过程调用.............................................................................................. 249 12.1 引言 ............................................................................................................ 249 12.2 远程过程调用模型 ....................................................................................... 249 12.3 传统过程调用和远程过程调用的比较 ........................................................... 250 12.4 远程过程调用的定义.................................................................................... 252 12.5 远程过程调用的有关问题............................................................................. 252 12.5.1 远程过程调用传送协议....................................................................... 253 12.5.2 Sun RPC ........................................................................................... 254 12.5.3 Xerox Courier .................................................................................... 254 12.5.4 Apollo RPC........................................................................................ 255 12.6 stub 过程简介............................................................................................... 256 12.7 rpcgen 简介 .................................................................................................. 256 12.8 分布式程序生成的例子 ................................................................................ 257 12.8.1 我们如何能够构造出一个分布式应用程序........................................... 257 12.9 小结 ............................................................................................................ 283 第十章 远程磁带的访问 .......................................................................................... 284 13.1 简介 ............................................................................................................ 284 13.2 Linux 磁带驱动器的处理 .............................................................................. 285 13.3 rmt 协议....................................................................................................... 285 13.4 rmt 服务器设计分析 ..................................................................................... 286 第十四章 WWW 上 HTTP 协议.................................................................................. 290 14.1 引言............................................................................................................ 290 14.2 HTTP 客户请求........................................................................................... 290 14.2.1 客户端 .............................................................................................. 290 14.2.2 服务器端........................................................................................... 290 14.2.3 Web 请求简介.................................................................................... 291 14.2.4 HTTP – HyperText Transfer Protocol 超文本传输协议 ........................... 295 14.3 Web 编程 .................................................................................................... 297 14.4 小结 ........................................................................................................... 301 附录 A 有关网络通信的服务和网络库函数................................................................... 302 附录 B Vi 使用简介..................................................................................................... 319 B.1 Vi 基本观念................................................................................................... 319 B.1.1 进入与离开.......................................................................................... 319 B.1.2 Vi 输入模式 ......................................................................................... 319 B.2 Vi 基本编辑................................................................................................... 320 B.2.1 删除与修改.......................................................................................... 320 B.3 Vi 进阶应用................................................................................................... 320 B.3.1 移动光标 ............................................................................................. 320 B.3.2 进阶编辑命令 ...................................................................................... 322 B.3.3 文件命令 ............................................................................................. 322 附录 C Linux 下 C 语言使用与调试简介 ...................................................................... 324 C.1 C 语言编程 ................................................................................................... 324 C.2 什么是 C? ..................................................................................................... 324 C.3 GNU C 编译器............................................................................................... 324 C.3.1 使用 GCC ............................................................................................ 324 C.3.2 GCC 选项 ............................................................................................ 325 C.3.3 优化选项 ............................................................................................. 325 C.3.4 调试和剖析选项................................................................................... 325 C.3.5 用 gdb 调试 GCC 程序.......................................................................... 326 C.4 另外的 C 编程工具 ........................................................................................ 330 C.4.1 Xxgdb.................................................................................................. 330 C.4.2 Calls .................................................................................................... 331 C.4.3 cproto .................................................................................................. 332 C.4.4 Indent .................................................................................................. 333 C.4.5 Gprof................................................................................................... 334 C.4.6 f2c 和 p2c ............................................................................................ 335 附录 D Ping 源码 ........................................................................................................ 336 附录 E TFTP 服务器程序源码 ..................................................................................... 362
### 回答1: 在Qt中,可以使用QTcpServer类来创建一个服务器,它可以同时接受多个客户端连接。当有新的客户端连接时,可以通过QAbstractSocket类的派生类QTcpSocket来与客户端进行通信。 首先,我们需要实例化一个QTcpServer对象,然后通过调用其listen()函数来监听指定的IP地址和端口。例如: QTcpServer *server = new QTcpServer(this); if (!server->listen(QHostAddress::Any, 1234)) { qDebug() << "Server could not start: " << server->errorString(); } else { qDebug() << "Server started!"; } 当有新的客户端连接时,QTcpServer会发出newConnection()信号,可以通过连接该信号的槽函数处理新的连接请求。在槽函数中,可以使用nextPendingConnection()函数来获取新的QTcpSocket对象,该对象可以用于与客户端进行通信。 例如: QObject::connect(server, &QTcpServer::newConnection, [=]() { QTcpSocket *clientSocket = server->nextPendingConnection(); qDebug() << "New client connected!"; }); 通过上述代码,在有新的客户端连接时,会打印"New client connected!"。 接下来,可以通过clientSocket对象来读取和写入数据,与客户端进行通信。例如,可以使用readyRead()信号来处理客户端发送的数据,并使用write()函数发送响应数据给客户端。 QObject::connect(clientSocket, &QTcpSocket::readyRead, [=]() { QByteArray data = clientSocket->readAll(); qDebug() << "Received data from client: " << data; // Send response to client clientSocket->write("Hello from server!"); }); 通过上述代码,在客户端发送数据时,会打印"Received data from client: "并显示接收的数据,并向客户端发送"Hello from server!"。 当需要断开与客户端连接时,可以使用disconnectFromHost()函数。 总结:在Qt中,可以通过QTcpServer类创建一个服务器,通过nextPendingConnection()函数获取客户端连接对象,再通过该对象与客户端进行通信并处理数据。通过连接newConnection()信号,可以实现多个客户端连接。 ### 回答2: 在Qt中,我们可以使用QTcpServer类来实现一个服务器连接多个客户端的功能。首先,我们创建一个QTcpServer的实例,并调用listen()函数来开始监听指定的端口。当有客户端连接服务器时,QTcpServer会自动创建一个新的QTcpSocket来处理与该客户端的通信。 为了连接多个客户端,我们可以使用一个容器(例如QList)来保存所有与客户端连接,每当有新的连接时,我们将其加入到容器中。当收到消息时,我们可以遍历容器中的所有连接,并向每个连接发送消息。 为了处理多个客户端连接请求,我们可以监听QTcpServer的newConnection()信号。当这个信号触发时,代表有新的客户端连接服务器。我们可以在这个信号的槽函数中使用nextPendingConnection()函数来获取与新客户端连接的套接字,并将其保存到容器中。 当给定的连接断开时,我们需要在容器中删除该连接。为了实现这个功能,我们可以利用QTcpSocket的disconnected()信号,该信号在连接断开时被触发。在这个信号的槽函数中,我们可以通过调用deleteLater()函数和从容器中删除该连接来释放相关资源。 总的来说,通过使用QTcpServer、QTcpSocket以及相关的信号和槽函数,我们可以在Qt中轻松地实现一个服务器连接多个客户端的网络应用。 ### 回答3: 在Qt中,我们可以使用QTcpServer类和QTcpSocket类来实现一个服务器连接多个客户端的功能。 首先,我们需要创建一个QTcpServer对象,并使用listen()函数来开始监听客户端连接。然后,我们可以使用newConnection()信号来接收客户端连接请求。 每当有新的客户端连接时,QTcpServer会自动触发newConnection()信号。我们可以在这个信号的槽函数中,创建一个新的QTcpSocket对象来处理与该客户端的通信。 创建新的QTcpSocket对象后,我们需要连接相应的信号和槽函数处理客户端的通信。常见的信号有readyRead()和disconnected(),分别表示接收到客户端发送的数据和客户端断开连接。我们可以在readyRead()信号的槽函数中读取客户端发送的数据,然后进行相应的处理。在disconnected()信号的槽函数中,我们可以释放相应的资源,并将客户端相关的QTcpSocket对象删除。 对于有多个客户端连接的情况,我们可以使用QList或QMap来存储所有的QTcpSocket对象,并通过客户端的唯一标识符来区分和管理每个客户端连接。 需要注意的是,在处理客户端的通信时,我们可能会遇到多线程或多线程事件循环的情况。因此,为了避免多个客户端之间的数据混乱和冲突,我们可能需要使用互斥锁或信号槽来进行线程间的同步和通信。 以上就是使用Qt实现一个服务器连接多个客户端的基本步骤。通过合理的设计和编码,我们可以实现一个高效、稳定和可扩展的服务器系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值