项目场景:
多线程服务器是对多进程服务器的改进,由于多进程服务器在创建进程时要消耗较大的系统资源,所以用线程来取代进程,这样服务处理程序可以较快的创建。
问题描述
盲目模仿多进程服务器的写法,归根结底还是自己没有掌握多进程和多线程的区别
模仿多进程服务器,写了多线程服务器。通过测试,多线程完成了多个socket连接并传输数据的任务
int main(int argc,char *argv[]){
int lfd,cfd;
int i=0;
int ret;
char buf[BUFSIZ];
pthread_t tid;
struct sockaddr_in srv_addr,clt_addr;
socklen_t clt_addr_len;
struct s_info s_info_array[256];
//memset(&saddr,0,sizeof(saddr));
bzero(&srv_addr,sizeof(srv_addr));
srv_addr.sin_family=AF_INET;
srv_addr.sin_port= htons(PORT);
srv_addr.sin_addr.s_addr= htonl(INADDR_ANY);
lfd= Socket(AF_INET,SOCK_STREAM,0);
Bind(lfd,(struct sockaddr *)&srv_addr, sizeof(srv_addr));
Listen(lfd,128);
while(1){
clt_addr_len = sizeof(clt_addr_len);
cfd= Accept(lfd,(struct sockaddr*)&clt_addr,&clt_addr_len);
s_info_array[i].cliaddr = clt_addr;
s_info_array[i].connfd = cfd;
ret= pthread_create(&tid,NULL,do_work,(void *)&s_info_array[i]);
if(ret==-1){
sys_err("pthread_create error");
}
pthread_detach(tid);
i++;
}
return 0;
}
服务端与2个客户端建立连接并接收数据:
客户端1:
客户端2:
原因分析:
子线程的exit退出,把主线程也给退出了:
exit用于结束正在运行的整个程序,它将参数返回给OS,把控制权交给操作系统;而return是退出当前函数,返回函数值,把控制权交给调用函数。
解决方案:
- return:使用return返回到上一级。
- break:使用break跳出当前循环。
进程与线程的比较:
1、进程:子进程是父进程的复制品,是获得父进程数据空间、堆和栈的复制品;而线程,相对与进程而言,线程是一个更加接近执行体的概念,它可以与同进程的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。两者都可以提高程序的并发度,提高程序运行效率和响应时间。
2、线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源管理和保护;而进程正相反。同时,线程适合于在SMP机器(简单来讲就是平时所说的双CPU系统,是对称多处理机中最常见的一种)上运行,而进程则可以跨机器迁移。
3、根本区别就一点:用多进程每个进程有自己的地址空间(address space),线程则共享地址空间。所有其它区别都是由此而来的:a、速度:线程产生的速度快,线程间的通讯快、切换快等,因为他们在同一个地址空间内;b、资源利用率:线程的资源利用率比较好也是因为他们在同一个地址空间内;c、同步问题:线程使用公共变量/内存时需要使用同步机制还是因为他们在同一个地址空间内。
推荐阅读 TCP并发服务器---多进程和多线程