accept函数是由客户端调用(一个TCP客户端连接多个服务器怎么样高效)

本文目录
一个TCP客户端连接多个服务器怎么样高效
服务器在调用listen和accept后,就会阻塞在accept函数上,accpet函数返回后循环调用accept函数等待客户的TCP连接。如果这时候又大量的用户并发发起connect连接,那么在listen有队列上限(最大可接受TCP的连接数)的情况下,有多少个connect会成功了。试验证明,当连接数远远高于listen的可连接数上限时,客户端的大部分TCP请求会被抛弃,只有当listen监听队列空闲或者放弃某个连接时,才可以接收新的连接,那么我们应该如何来避免这种情况出现?
分析:
(一)客户端
客户端运行初期完成所设定的一定量的socket创建和相应的处理线程的创建,然后使用条件变量来完成线程同步,直到最后一个线程创建完成,才向所有线程发出广播通知,让所有线程并发调用connect,连接成功则关闭连接,失败则返回,如下代码所示。
socket创建和线程创建:
int testCount=300; //并发用户数
/*
每个进程需要自己独立的栈空间,linux下默认栈大小是10M,在32位的机子上一个进程需要4G的内存空间,去掉自己的栈空间全局程序段空间,一般只有3G内存可以用,创建线程时就需要从这3G的空间中分配10M出来,所以最多可以分配300个线程。当然这里还可以使用多个进程,每个进程300个线程的方式来进一步扩大并发量。
*/
int sockfd;
pthread_t ntid;
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(SERVER_PORT);
inet_pton(AF_INET,argv,&servaddr.sin_addr);
int testCaseIndex=0;
for(testCaseIndex=0;testCaseIndex《testCount;testCaseIndex++)
{
sockfd=socket(AF_INET,SOCK_STREAM,0);
//为每个并发客户端创建一个socket
if(sockfd==-1)
{
printf("socket established error: %s\n",(char*)strerror(errno));
return -1;
}
if( pthread_create(&ntid)!=0)
{
printf("create thread error :%s\n",strerror(errno));
return -1;
}
//为每个并发客户端创建一个线程来执行connect
}
printf("%d client has initiated\n",testCaseIndex);
并发客户端的线程实现:线程阻塞在条件变量上(只有条件满足了并且发起唤醒动作,线程才开始执行)。
int sockfd=*((int*)arg);
{
pthread_cond_wait(&cond,&mut);
//在条件变量上等待条件满足!
//阻塞返回后立即解锁,防止互斥量加锁带来的阻塞
pthread_mutex_unlock(&mut);
int conRes=0;
conRes=connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
//线程执行connect连接,每个线程在接到唤醒信号后,才可以执行该语句,来模拟多个线程的并发调用。
if(conRes==-1)
{
printf("connect error: %s\n",strerror(errno));
return 0;
}
}
当条件满足时,唤醒阻塞在条件变量上的线程:
while(1)
{
sleep(2);
pthread_cond_broadcast(&cond); //在所有线程创建完成后才进行唤醒。
socket通信问题
亲,不知道该说你对,还是你错。
服务器程序在一个端口监听,这个端口我们暂称为监听端口,当该端口收到新的请求链接时,服务器会创建一个新的端口来与客户通信,accept函数 不知道你熟悉不,你可以去看看msdn accept返回的就是新的socket 也就是与客户通信的套接字.这个新套接字的端口是随机的,不会通知客户端,因为没有必要;
客户端调用connect函数后 会向服务器发送链接请求,当服务器accept收到后,就会创建端口与客户端继续交互,创建套接字的这个过程对客户端来说完全是透明的. 这个端口仅仅负责这个链接的通信,(这时候大量的客户端向服务器的同一端口发送信息)所以你说的是错误的,监听端口是负责监听,就说你发数据它也不会处理。所以不存在(把接收的数据准确的分配到各个不同的会话中的)
还有你说对了一点 每当有一个新的链接时 服务器的确会分配一个端口与客户端通信,这个通信的过程不再走监听端口,监听端口是负责监听,不负责通信(收发数据)。每当一个新链接就创建一个线程来处理通信的话,太浪费资源,你可以参考下io完成端口讲的很详细。
客户端 socket fd 是怎么传入到服务器端 accept 方法的
服务器端和客户端都是通过SOCKET来进行通信的,首先产生一个 socket实例,通过这个实例,服务器端调用accept这个方法接收来自客户端发送的信息.但是在产生socket实例的时候必须初始化一个端口.用来负责接受客户端的请求!
客户端要给服务器发送消息也必须产生一个socket实例,初始化的时候必须指定服务器的IP地址,并且指定服务接收的端口号,这样客户端才能找到服务器要接收的地方,找到地方就可以发送过去了。和你写信一样。找到地址
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
BufferedReader wt = new BufferedReader(new InputStreamReader(System.in));
这个只是用来获取一个从键盘的一个流.传送给服务器端的数据都是通过流来表示的。意思是是键盘输入的一个字节转化成字符流.并输出或者写入!

更多文章:
全球新冠肺炎疫情背景下航运发展(盐田港复苏日志:半年历劫从“低谷”到“爆仓” 疫情之后巨轮如何越洋航行)
2026年9月7日 17:10
matlab求解带字母参数方程组(我想matlab求一个关于x,y的方程组 ab c d f e h m n 都是参数)
2026年9月7日 16:30
oracle中的循环语句(下面哪个不是oracle程序设计中的循环语句 a for)
2026年9月7日 15:30
电脑里2个系统怎么删除一个(电脑开机显示有两个系统,如何删除一个)
2026年9月7日 12:20
scrollthrough意思(“scroll”是什么意思)
2026年9月7日 08:00
怎么激活keygen(注册机如何激活cad2008一个简单激活cad2008的方法)
2026年9月7日 06:30



