-
父进程
负责监听,处理客户端的连接请求,也就是在父进程中循环调用 accept() 函数;
创建子进程:建立一个新的连接,就创建一个新的子进程,让这个子进程和对应的客户端通信;
回收子进程资源:子进程退出回收其内核 PCB 资源,防止出现僵尸进程。 -
子进程
负责通信,基于父进程建立新连接之后得到的文件描述符,和对应的客户端完成数据的接收和发送;
与客户端建立链接;
收发数据:send() / write(),recv() / read()。
创建线程
多线程部分程序
1、创建线程:
注意,第三个参数是void *类型,这就意味着当你需要传多个参数的时候可以把他们封装在一个结构体中。
头文件
#include <pthread.h>
#include <sys/select.h>
创建线程
int pthread_create(
pthread_t *restrict tidp, //新创建的线程ID指向的内存单元。
const pthread_attr_t *restrict attr, //线程属性,默认为NULL
void *(*start_rtn)(void *), //线程函数
void *restrict arg //线程函数的参数
);
2、线程分离:
作用:从状态上实现线程分离,注意不是指该线程独自占用地址空间。
线程分离状态:指定该状态,线程主动与主控线程断开关系。线程结束后(不会产生僵尸线程),其退出状态不由其他线程获取,而直接自己自动释放(自己清理掉PCB的残留资源)。
int pthread_detach(pthread_t thread); 成功:0;失败:错误号
3、线程锁
保护数据不会被同时修改(其实互斥锁也可以实现)。
typedef pthread_mutex_t mutex;
pthread_mutex_lock(&mutex);
pthread_mutex_destroy(&mutex);
部分程序代码
主函数(父进程)
任务:主要负责重复select,做好rdset集合并将数据传递给子进程(通过自定义结构体)。
int main()
{
//完成线程锁的初始化
pthread_mutex_init(&mutex,NULL);
// 创建监听的lfd
int lfd = socket(AF_INET, SOCK_STREAM, 0);
// 定义服务器性质,并储存在sockaddr_in addr中;绑定。
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(9999);
addr.sin_addr.s_addr = INADDR_ANY;
bind