服务器如何给多个客户端分配端口号

在一台计算机上,使用socket通信时,不同进程区分网络通信的连接依靠三个参数:通信所用协议、地址IP、端口号。

对于服务器端来说,通过bind、listen,之后accept建立新的连接,accept返回新连接的句柄,这样就建立了一条连接。那么新建立的连接使用的端口号是否和listen所用端口号相同呢?以前我一直以为服务器会随机分配一个新的端口号来使用,后来发现错了。

因为1、现在使用多路IO复用epoll等,配置好点的服务器可以支持数十万个并发连接,端口号为16位,最多才2^16-1,且加上一些常用的端口号不能使用,可用的端口号都没那么多。2、现在服务器大多使用防火墙,防火墙只对特定端口开放。如果accept随机分配端口号,会不能通过防火墙。

TCP/IP协议中,IP协议是端到端的协议,它只是负责把把数据发送到端,交付给上层而已。运输层TCP、UDP加上了端口号,目的是区分不同的应用。其中TCP还实现了流量控制、可靠传输等,而UDP只是应该是没有对IP层数据进行处理了。

在以往的知识中,我知道一个应用程序只能使用一个端口号,如果accept返回的句柄还是使用listen的端口号,那么怎么实现通信呢?如果建立多个连接,应用程序怎么区收到的信息来自哪个客户端呢?

现在才理解到accept返回的句柄建立的连接包括四部分:源IP、源端口号、目的IP、目的端口号。这样在一个应用程序中,就算和多个客户端建立连接,在收到数据后,应用程序通过目的IP和目的端口号也能区分是哪一条连接。

通过一个echo服务器来验证一下,client和server都在同一台机器上:

服务器监听8000端口,在未建立连接时,可以看到在监听8000

在通过一个客户端建立连接后,可以看到建立了一条连接,服务器端的端口号是8000,监听的还是8000。

在连接一个客户端,可以看到建立了两条连接,服务器端都是使用8000,监听的还是8000。

下面是server端代码:

#include<stdio.h>
#include<sys/socket.h>
#include<unistd.h>
#include<errno.h>
#include<netinet/in.h>
void str_echo(int sockfd)
{
	int n;
	char buf[1024];
again:
	while((n=read(sockfd,buf,1024))>0)
	{
		write(sockfd,buf,n);
	}
	if(n<0&&errno==EINTR)
		goto again;
	else if(n<0)
		printf("str_error:read error");
}
int main(int argc, char **argv)
{
	int listenfd, connfd;
	pid_t childid;
	socklen_t clilen;
	struct sockaddr_in cliaddr, servaddr;

	listenfd=socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr,sizeof(servaddr));
	servaddr.sin_family=AF_INET;
	servaddr.sin_addr.s_addr=htonl(INADDR_ANY);//host IP
	servaddr.sin_port=htons(8000);//port

	bind(listenfd,(struct sockaddr*)&servaddr,sizeof(struct sockaddr));

	listen(listenfd,5);//最多处理五个监听

	for(;;)
	{
		clilen=sizeof(cliaddr);
		//进场阻塞在accept上
		connfd=accept(listenfd, (struct sockaddr*)&cliaddr,&clilen);

		if(childid=fork()==0)//child
		{
			close(listenfd);//在子进程中关闭监听
			str_echo(connfd);//处理监听的连接
			exit(0);
		}
	}
	close(listenfd);
}

客户端代码:

#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
void str_cli(FILE *fp, int sockfd)
{
	char sendline[1024],recvline[1024];
	while(fgets(sendline, 1024, fp)!=NULL)
	{
		//发给Server
		write(sockfd,sendline,sizeof(sendline));

		//读Server
		if(read(sockfd,recvline,1024)==0)
		{
			printf("str_cli:server terminated prematurely\n");
			exit(0);
		}
		//fputs(recvline,stdout);
		printf("%s",recvline);
	}
}
int main(int argc, char **argv)
{
	int sockfd;
	struct sockaddr_in servaddr;

	if(argc!=2)
	{
		printf("usage:client IPaddress \n");
		exit(0);
	}
	sockfd=socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr,sizeof(servaddr));
	servaddr.sin_family=AF_INET;
	servaddr.sin_port=htons(8000);

	//把输入的IP存到sin_addr中
	inet_pton(AF_INET,argv[1],&servaddr.sin_addr);
	printf("server IP:%s\n",argv[1]);
	//建立连接
	connect(sockfd,(struct sockaddr*)&servaddr,sizeof(struct sockaddr));

	str_cli(stdin,sockfd);

	exit(0);
}
时间: 2024-10-23 11:37:55

服务器如何给多个客户端分配端口号的相关文章

node.js---ip地址和端口号

IP地址和端口号:  .js代码 1 //1.加载http具名核心模块 2 var http=require('http') 3 4 //2.创建server 5 var server=http.createServer() 6 7 //3.监听request请求事件,设置请求处理函数 8 server.on('request',function(req,res){ 9 console.log('\n收到请求了,请求路径是:'+req.url) 10 console.log("客户端IP地址:&

腾讯云服务器通过设置安全组放行对外端口号

在腾讯云服务器采购过程中,一般在采购的时候会让你开启默认的安全组策略,此时默认开启的只有几个常规端口,如80的Web网站端口,3306的远程桌面端口等,有时候我们服务器应用还需要开启其他自定义端口号,此时在服务器部署相应的应用后,我们还需要在腾讯云控制台的安全组功能中放行对应的端口号,否则这个应用将会因为端口不通而无法访问.例如,我们往服务器上安装了Sqlserver数据,此时就需要在安全组中开启Sqlserver数据库默认对外的端口访问权限,否则其他机器将无法访问到此Sqlserver数据库.

浏览器与服务器间的交互(客服端 &lt;---&gt; 服务器)

浏览器与服务器间的交互(客服端 <---> 服务器) 请求--->处理--->响应 对类HttpContext 内部成员的使用 例如 :Request .Response . Cookie . Session .GetSection  . . . /////~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * * 然而  一般处理程序 既为 中间阶段的 处理 层面 1 public void Pr

二十五、客户端/服务端架构,网络基础

一.软件开发的架构 我们了解的涉及到两个程序之间通讯的应用大致可以分为两种: 第一种是应用类:qq,微信.网盘,优酷这一类是属于需要安装的桌面应用 第二种是web类:比如百度.知乎.博客园等使用浏览器就可以直接使用的应用 这些应用的本质其实都是两个程序之间的通讯,而这两个分类又对应两个软件开发的构架 C/S即:Client与Server ,中文意思:客户端与服务器端架构,这种架构也是从用户层面(也可以是物理层面)来划分的. 这里的客户端一般泛指客户端应用程序EXE,程序需要先安装后,才能运行在用

关于发邮件的服务器的端口号

今天搞一个发邮件的小功能,一切参数设置好,就是服务器没响应. 一开始怀疑是邮件服务器设置不对,邮件服务器和outlook中找到的是一致的. 怀疑端口号25不对.大部分资料都说是25呀. ... 后来找到这个网页,说 Usually an outgoing server employs port 25: it's the default SMTP port. However, some IPs deny its use because of the massive spam and malware

Linux 查看服务器开放的端口号

在讨论这个问题前,我们先来了解一下物理端口.逻辑端口.端口号等计算机概念. 端口相关的概念: 在网络技术中,端口(Port)包括逻辑端口和物理端口两种类型.物理端口指的是物理存在的端口,如ADSL Modem.集线器.交换机.路由器上用 于连接其他网络设备的接口,如RJ-45端口.SC端口等等.逻辑端口是指逻辑意义上用于区分服务的端口,如TCP/IP协议中的服务端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等.由于物理端口和逻辑端口数量较多,为了对端

[Java聊天室服务器]实战之五 读写循环(服务端)

前言 学习任何一个稍有难度的技术,要对其有充分理性的分析,之后果断做出决定---->也就是人们常说的"多谋善断":本系列虽然涉及的是socket相关的知识,但学习之前,更想和广大程序员分享的是一种心境:学习是一个循序渐进的过程,心态应该随时调节,保持戒骄戒躁的状态.比如最近在看网易公开课MIT<算法导论>,老师提到,学习算法之前要计算机数学+离散数学+概率论等课程的知识,所以一直学不好算法的程序员不妨从基础入手,这都是中国式教育惹的祸啊!(此处省略一万字......)

C#使用Socket实现一个socket服务器与多个socket客户端通信

在分布式调度系统中,如果要实现调度服务器与多台计算节点服务器之间通信,采用socket来实现是一种实现方式,当然我们也可以通过数据存储任务,子节点来完成任务,但是往往使用数据作为任务存储都需要定制开发,要维护数据库中任务记录状态等等.开发的东西还是有点多,而且还不够灵活.因此,我个人是比较偏向于使用socket来实现任务的调度工作.原因:使用socket实现调度比较灵活,而且扩展性都比较好. 实现思路:调度服务器要实现调度工作,它必须与所有计算节点之间建立连接.而且他需要知道每台计算节点的任务状

Android版网络办公系统应用客户端+服务端

该项目源码是Android版网络办公系统应用客户端+服务端,也是一个简单的网上办公系统的Android客户端,项目有服务端和客户端部分的源码的,客户端开发环境eclipse  AVD版本 4.0服务器 phpStudy 2013集成环境 Apache+php5.3+ISAPI模式 phpStudy 2013集成环境绿色版下载http://www.phpstudy.net/phpstudy/phpStudy2013d.zip官网   http://www.phpstudy.net/ android