欢迎访问我的博客: http://www.alenchou.org/blog/
- 循环服务器:在服务器端使用while死循环忙等待客户端的连接请求,有请求的话处理连接。这样只能是处理完一个连接请求之后才能进行下一次的连接请求的处理
TCP循环服务器伪代码如下:
//sever: #include <...> int main() { socket(); 初始化本地地址; bind(); listem(); while(1){ accept(); recv(); ... send(); } ... } //client: #include <...> int main() { socket(); 初始化客户端本地地址; connect(); send(); recv(); ... ... }- 简单的并发服务器模型:
多进程同时等待连接:在服务器端,首先创建n个进程,每个进程独自处理客户端连接请求。
//server: #include <...> int main() { socket(); 初始化服务器端本地地址; bind(); listen(); for(i=0;i<创建的进程数;i++){ pid[i] = fork(); if(pid[i] == 0){ while(1){ accept(); recv(); ... send(); } } } while(1); ... } //client: #include <...> int main() { socket(); 初始化客户端本地地址; connect(); send(); recv(); ... ... }- 高级并发服务器模型:
单客户端单进程,统一accept():TCP并发服务器,在处理客户端请求之前,先分叉几个子进程,对于多个客户端的请求,由多个子进程进行处理,和循环服务器相比较并发的TCP程序,在处理客户端请求时不是简单的使用while进行客户端请求的串行处理。这样的服务器从总体上看,是一个任务分配的过程,主程序接受任务并进行任务分发,fork出来的进程处理主程序分发来的客户端的请求任务并进行处理和响应,最后的连接关闭在处理程序中进行。
//server: #include <...> int main() { socket(); 初始化服务器端本地地址; bind(); listen(); while(1){ s_c = accept(); if(sc > 0){ if(fork() > 0){ close(s_c); }else{ recv(); ... send(); close(s_c); } } } } //client: #include <...> int main() { socket(); 初始化客户端本地地址; connect(); send(); recv(); ... ... }单客户端单线程,统一accept():与进程相比,线程有很多优点,例如速度快,占用资源少,数据可以共享。
//server: #include <...> handle_request(void *argv) { recv(); send(); } int main() { pthread_t thread_do; socket(); 初始化服务器端本地地址; bind(); listen(); while(1){ s_c = accepet(); if(s_c > 0){ int err = pthread_create(&thread_do,NULL,handle_request,(void *)&s_c); } } } //client: #include <...> int main() { socket(); 初始化客户端本地地址; connect(); send(); recv(); ... ... }单客户端单线程,各线程独自accept(),使用互斥锁:各线程独自accept的时候需要注意的是为了防止冲突,必须在accept()调用之前必须锁定,调用函数accpet之后,释放锁,这和前面使用线程的模型不同,因为前面的是在while中统一accept后然后创建线程处理客户端的业务,然而在当前这个模型中,是在每个线程各自的处理过程中有accept,所以为了避免端口,ip等资源争用产生的死锁所以使用了线程互斥锁。
//server:
#include <...>
pthread_mutex_t ALOCK = PTHREAD_MUTEX_INITIALIZER;
void *handle_request(void *argv)
{
int s_s = *((int *)argv);
int s_c;
for(;;){
pthread_mutex_lock(&ALOCK);
s_c = accept();
pthread_mutex_unlock(&ALOCK);
recv();
send();
...
}
}
int main()
{
int s_s;
socket();
初始化本地地址;
bind();
listen(s_s);
pthread_t thread_do[可接受客户端数量];
for(i = 0;i<可接受客户端数量;i++){
pthread_create(&thread_do[i],NULL,handle_request,(void *)s_s);
}
for(i = 0;i<可接受客户端数量;i++){
pthread_join(thread_do[i],NULL);
}
}
//client:
#include <...>
int main()
{
socket();
初始化客户端本地地址;
connect();
send();
recv();
...
...
}