概念
- 这篇博客我们利用多线程解决服务器并发问题
- 进程是资源分配最小的单位,线程是CPU调度的最小单位
- 多进程与多线程比较(下图取自网络,原作者不详)
对比维度 | 多进程 | 多线程 | 总结 |
数据共享、同步 | 数据共享复杂,需要用IPC;数据是分开的,同步简单 | 因为共享进程数据,数据共享简单,但也是因为这个原因导致同步复杂 | 各有优势 |
内存、CPU | 占用内存多,切换复杂,CPU利用率低 | 占用内存少,切换简单,CPU利用率高 | 线程占优 |
创建销毁、切换 | 创建销毁、切换复杂,速度慢 | 创建销毁、切换简单,速度很快 | 线程占优 |
编程、调试 | 编程简单,调试简单 | 编程复杂,调试复杂 | 进程占优 |
可靠性 | 进程间不会互相影响 | 一个线程挂掉将导致整个进程挂掉 | 进程占优 |
分布式 | 适应于多核、多机分布式;如果一台机器不够,扩展到多台机器比较简单 | 适应于多核分布式 | 进程占优 |
代码实现
- 服务器端利用多线程编程
- 注意编译的时候加上-lpthread ,否则会出现如下编译错误
undefined reference to `pthread_create’
collect2: ld 返回 1
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void *thread_worker(void *arg);
int *p;
int main(int argc, char **argv)
{
int socket_fd, connect_fd = -1;
struct sockaddr_in serv_addr;
pthread_t tid;
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if(socket_fd < 0 )
{
printf("create socket failure: %s\n", strerror(errno));
return -1;
}
printf("socket create fd[%d]\n", socket_fd);
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(9998);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if( bind(socket_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0 )
{
printf("create socket failure: %s\n", strerror(errno));
return -2;
}
printf("socket bind ok\n", socket_fd);
listen(socket_fd, 13);
printf("listen fd ok\n", socket_fd);
while(1)
{
printf("waiting for client's connection......\n", socket_fd);
connect_fd = accept(socket_fd, NULL, NULL);
p=&connect_fd;
if(connect_fd < 0)
{
printf("accept new socket failure: %s\n", strerror(errno));
return -2;
}
printf("accept ok, return connect_fd: [%d]\n", connect_fd);
pthread_create (&tid, NULL,thread_worker, (void *)p);
}
close(socket_fd);
}
void *thread_worker(void *arg)
{
char buf[1024];
int cli_fd =*p;
memset(buf, 0, sizeof(buf));
while(1){
read(cli_fd, buf, sizeof(buf));
printf("read '%s' from client\n", buf);
printf("send data to client:");
fgets(buf,sizeof(buf),stdin);
write(cli_fd, buf, strlen(buf));
sleep(1);
}
close(cli_fd);
return NULL;
}