TCP网络服务器模型
来源:互联网 发布:闰年的判断c语言 编辑:程序博客网 时间:2024/05/22 08:13
服务器模型
1、循环服务器
实现流程:
1)、服务器端从连接请求队列中提取请求,建立连接并返回已连接的套接字。
2)、服务器端通过以连接的套接字循环接收数据,处理并发给客户端,直到客户端关闭连接。
3)、服务器端关闭已连接的套接字,返回步骤 1)。
特点:
1.服务器采用循环嵌套实现,外层循环一次提取每个客户端的链接请求,建立TCP链接。内层循环接收连接并处理当前客户端的所有数据,知道客户端关闭连接。
如果当前客户端没有处理结束,其他客户端必须一直等待。
2.采用这种循环服务器端无法实现对多个客户端服务。适应于客户端连接时间短的情况。
3.同一时刻只能处理一个客户端的请求,一般很少使用
服务器代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
intmain()
{
//定义结构体变量,作为bind函数的参数
structsockaddr_inservAddr;
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family=PF_INET;
servAddr.sin_port=htons(8888);
servAddr.sin_addr.s_addr=inet_addr("127.0.0.1");
//创建套接字
//返回值为新创建的socket的文件描述符,失败-1
intservFd=socket(PF_INET,SOCK_STREAM,0);
if(servFd<0)
{
perror("socket error!");
return-1;
}
printf("socket ok!\n");
//绑定地址信息
intret=bind(servFd,(structsockaddr*)&servAddr,sizeof(servAddr));
if(ret<0)
{
perror("bind error!");
close(servFd);
return-1;
}
printf("bind ok!\n");
//创建监听队列
ret=listen(servFd,10);
if(ret<0)
{
perror("listen error!");
close(servFd);
return-1;
}
printf("listening.....\n");
while(1)
{
//接收连接请求
intconnFd=accept(servFd,NULL,NULL);
if(connFd<0)
{
perror("accept error!");
close(servFd);
return-1;
}
printf("accept ok!\n");
charbuf[1024]={0};
//接收消息
ret=recv(connFd,buf,sizeof(buf),0);
if(ret<0)
{
perror("recv error!");
close(servFd);
close(connFd);
return-1;
}
printf("recv from client: %s\n",buf);
strcat(buf,"+++");
send(connFd,buf,sizeof(buf),0);
//关闭套接字
close(connFd);
sleep(10);
}
close(servFd);
return0;
}
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
intmain()
{
//定义结构体变量,作为bind函数的参数
structsockaddr_inservAddr;
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family=PF_INET;
servAddr.sin_port=htons(8888);
servAddr.sin_addr.s_addr=inet_addr("127.0.0.1");
//创建套接字
//返回值为新创建的socket的文件描述符,失败-1
intservFd=socket(PF_INET,SOCK_STREAM,0);
if(servFd<0)
{
perror("socket error!");
return-1;
}
printf("socket ok!\n");
//绑定地址信息
intret=bind(servFd,(structsockaddr*)&servAddr,sizeof(servAddr));
if(ret<0)
{
perror("bind error!");
close(servFd);
return-1;
}
printf("bind ok!\n");
//创建监听队列
ret=listen(servFd,10);
if(ret<0)
{
perror("listen error!");
close(servFd);
return-1;
}
printf("listening.....\n");
while(1)
{
//接收连接请求
intconnFd=accept(servFd,NULL,NULL);
if(connFd<0)
{
perror("accept error!");
close(servFd);
return-1;
}
printf("accept ok!\n");
charbuf[1024]={0};
//接收消息
ret=recv(connFd,buf,sizeof(buf),0);
if(ret<0)
{
perror("recv error!");
close(servFd);
close(connFd);
return-1;
}
printf("recv from client: %s\n",buf);
strcat(buf,"+++");
send(connFd,buf,sizeof(buf),0);
//关闭套接字
close(connFd);
sleep(10);
}
close(servFd);
return0;
}
客户端代码:
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
intmain()
{
//定义结构体变量,该变量保存的服务器的地址信息,作为connect的参数
structsockaddr_inservAddr;
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family=PF_INET;
servAddr.sin_port=htons(8888);
servAddr.sin_addr.s_addr=inet_addr("127.0.0.1");
//创建套接字
intcliFd=socket(PF_INET,SOCK_STREAM,0);
if(cliFd<0)
{
perror("socket error!");
return-1;
}
printf("socket ok!\n");
//发起连接请求
intret=connect(cliFd,(structsockaddr*)&servAddr,sizeof(servAddr));
if(ret<0)
{
perror("connect error!");
close(cliFd);
return-1;
}
printf("connect ok!\n");
charbuf[1024]="hello world";
//发送消息
ret=send(cliFd,buf,sizeof(buf),0);
if(ret<0)
{
perror("send error!");
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
intmain()
{
//定义结构体变量,该变量保存的服务器的地址信息,作为connect的参数
structsockaddr_inservAddr;
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family=PF_INET;
servAddr.sin_port=htons(8888);
servAddr.sin_addr.s_addr=inet_addr("127.0.0.1");
//创建套接字
intcliFd=socket(PF_INET,SOCK_STREAM,0);
if(cliFd<0)
{
perror("socket error!");
return-1;
}
printf("socket ok!\n");
//发起连接请求
intret=connect(cliFd,(structsockaddr*)&servAddr,sizeof(servAddr));
if(ret<0)
{
perror("connect error!");
close(cliFd);
return-1;
}
printf("connect ok!\n");
charbuf[1024]="hello world";
//发送消息
ret=send(cliFd,buf,sizeof(buf),0);
if(ret<0)
{
perror("send error!");
close(cliFd);
return -1;
}
printf("send ok!\n");
memset(buf, 0, sizeof(buf));
recv(cliFd, buf, sizeof(buf), 0);
printf("recv from server %s\n", buf);
//关闭套接字
close(cliFd);
return 0;
}
2、并发服务器
>>>多进程的并发服务器
>>>多线程的并发服务器
>>>IO多路复用的并发服务器
>>>多进程的并发服务器
>>>多线程的并发服务器
>>>IO多路复用的并发服务器
>>>多进程的并发服务器
只要有客户端连接服务器,服务器就创建子进程与客户端通信
创建子进程后,父进程----继续等待其他客户端的连接
子进程----与客户端通信
总结:多进程服务器,比较浪费资源,适合于客户端数量较少,但是长连接的情况
服务器代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
voidsigFunc(intsigNo)
{
if(sigNo==SIGCHLD)
{
wait(NULL);
}
}
intmain()
{
//定义结构体变量,作为bind函数的参数
structsockaddr_inservAddr;
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family=PF_INET;
servAddr.sin_port=htons(8888);
servAddr.sin_addr.s_addr=inet_addr("127.0.0.1");
//创建套接字
//返回值为新创建的socket的文件描述符,失败-1
intservFd=socket(PF_INET,SOCK_STREAM,0);
if(servFd<0)
{
perror("socket error!");
return-1;
}
printf("socket ok!\n");
//绑定地址信息
intret=bind(servFd,(structsockaddr*)&servAddr,sizeof(servAddr));
if(ret<0)
{
perror("bind error!");
close(servFd);
return-1;
}
printf("bind ok!\n");
//创建监听队列
ret=listen(servFd,10);
if(ret<0)
{
perror("listen error!");
close(servFd);
return-1;
}
printf("listening.....\n");
while(1)
{
//接收连接请求
intconnFd=accept(servFd,NULL,NULL);
if(connFd<0)
{
perror("accept error!");
close(servFd);
return-1;
}
printf("accept ok!\n");
//创建子进程
pid_tpid;
while((pid=fork())<0);
if(0==pid)
{
close(servFd);
charbuf[1024]={0};
while(1)
{
//接收消息
memset(buf,0,sizeof(buf));
ret=recv(connFd,buf,sizeof(buf),0);
if(ret<0)
{
perror("recv error!");
close(connFd);
return-1;
}
elseif(0==ret)
{
printf("client shutdown!\n");
break;
}
printf("recv from client: %s\n",buf);
memset(buf,0,sizeof(buf));
printf("server:");
gets(buf);
send(connFd,buf,sizeof(buf),0);
}
//关闭套接字
close(connFd);
exit(0);
}
else
{
close(connFd);
signal(SIGCHLD,sigFunc);
}
}
close(servFd);
return0;
}
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
voidsigFunc(intsigNo)
{
if(sigNo==SIGCHLD)
{
wait(NULL);
}
}
intmain()
{
//定义结构体变量,作为bind函数的参数
structsockaddr_inservAddr;
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family=PF_INET;
servAddr.sin_port=htons(8888);
servAddr.sin_addr.s_addr=inet_addr("127.0.0.1");
//创建套接字
//返回值为新创建的socket的文件描述符,失败-1
intservFd=socket(PF_INET,SOCK_STREAM,0);
if(servFd<0)
{
perror("socket error!");
return-1;
}
printf("socket ok!\n");
//绑定地址信息
intret=bind(servFd,(structsockaddr*)&servAddr,sizeof(servAddr));
if(ret<0)
{
perror("bind error!");
close(servFd);
return-1;
}
printf("bind ok!\n");
//创建监听队列
ret=listen(servFd,10);
if(ret<0)
{
perror("listen error!");
close(servFd);
return-1;
}
printf("listening.....\n");
while(1)
{
//接收连接请求
intconnFd=accept(servFd,NULL,NULL);
if(connFd<0)
{
perror("accept error!");
close(servFd);
return-1;
}
printf("accept ok!\n");
//创建子进程
pid_tpid;
while((pid=fork())<0);
if(0==pid)
{
close(servFd);
charbuf[1024]={0};
while(1)
{
//接收消息
memset(buf,0,sizeof(buf));
ret=recv(connFd,buf,sizeof(buf),0);
if(ret<0)
{
perror("recv error!");
close(connFd);
return-1;
}
elseif(0==ret)
{
printf("client shutdown!\n");
break;
}
printf("recv from client: %s\n",buf);
memset(buf,0,sizeof(buf));
printf("server:");
gets(buf);
send(connFd,buf,sizeof(buf),0);
}
//关闭套接字
close(connFd);
exit(0);
}
else
{
close(connFd);
signal(SIGCHLD,sigFunc);
}
}
close(servFd);
return0;
}
客户端代码:
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
intmain()
{
//定义结构体变量,该变量保存的服务器的地址信息,作为connect的参数
structsockaddr_inservAddr;
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family=PF_INET;
servAddr.sin_port=htons(8888);
servAddr.sin_addr.s_addr=inet_addr("127.0.0.1");
//创建套接字
intcliFd=socket(PF_INET,SOCK_STREAM,0);
if(cliFd<0)
{
perror("socket error!");
return-1;
}
printf("socket ok!\n");
//发起连接请求
intret=connect(cliFd,(structsockaddr*)&servAddr,sizeof(servAddr));
if(ret<0)
{
perror("connect error!");
close(cliFd);
return-1;
}
printf("connect ok!\n");
charbuf[1024];
while(1)
{
memset(buf,0,sizeof(buf));
printf("client:");
gets(buf);
if(0==strcmp(buf,"quit"))
{
break;
}
//发送消息
ret=send(cliFd,buf,sizeof(buf),0);
if(ret<0)
{
perror("send error!");
close(cliFd);
return-1;
}
printf("send ok!\n");
memset(buf,0,sizeof(buf));
recv(cliFd,buf,sizeof(buf),0);
printf("recv from server %s\n",buf);
}
//关闭套接字
close(cliFd);
return0;
}
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
intmain()
{
//定义结构体变量,该变量保存的服务器的地址信息,作为connect的参数
structsockaddr_inservAddr;
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family=PF_INET;
servAddr.sin_port=htons(8888);
servAddr.sin_addr.s_addr=inet_addr("127.0.0.1");
//创建套接字
intcliFd=socket(PF_INET,SOCK_STREAM,0);
if(cliFd<0)
{
perror("socket error!");
return-1;
}
printf("socket ok!\n");
//发起连接请求
intret=connect(cliFd,(structsockaddr*)&servAddr,sizeof(servAddr));
if(ret<0)
{
perror("connect error!");
close(cliFd);
return-1;
}
printf("connect ok!\n");
charbuf[1024];
while(1)
{
memset(buf,0,sizeof(buf));
printf("client:");
gets(buf);
if(0==strcmp(buf,"quit"))
{
break;
}
//发送消息
ret=send(cliFd,buf,sizeof(buf),0);
if(ret<0)
{
perror("send error!");
close(cliFd);
return-1;
}
printf("send ok!\n");
memset(buf,0,sizeof(buf));
recv(cliFd,buf,sizeof(buf),0);
printf("recv from server %s\n",buf);
}
//关闭套接字
close(cliFd);
return0;
}
>>>多线程的并发服务器
只要有客户端连接服务器,服务器就创建子线程与客户端通信
由于在创建子线程时,以及销毁子线程时,比较浪费时间,一般可以使用线程池
多线程存在的问题:存在资源竞争以及同步的问题
总结:适合于客户端数量较少,但是长连接的情况
只要有客户端连接服务器,服务器就创建子线程与客户端通信
由于在创建子线程时,以及销毁子线程时,比较浪费时间,一般可以使用线程池
多线程存在的问题:存在资源竞争以及同步的问题
总结:适合于客户端数量较少,但是长连接的情况
服务器代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
void*threadFunc(void*arg)
{
intconnFd=*((int*)arg);
charbuf[1024]={0};
while(1)
{
memset(buf,0,sizeof(buf));
//接收消息
intret=recv(connFd,buf,sizeof(buf),0);
if(ret<0)
{
perror("recv error!");
close(connFd);
pthread_exit((void*)-1);
}
elseif(0==ret)
{
printf("client shutdown!\n");
break;
}
printf("recv from client: %s\n",buf);
memset(buf,0,sizeof(buf));
printf("server:");
gets(buf);
send(connFd, buf, sizeof(buf), 0);
}
close(connFd);
pthread_exit(NULL);
}
int main()
{
//定义结构体变量,作为bind函数的参数
struct sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = PF_INET;
servAddr.sin_port = htons(8888);
servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//创建套接字
//返回值为新创建的socket的文件描述符,失败-1
int servFd = socket(PF_INET, SOCK_STREAM, 0);
if(servFd < 0)
{
perror("socket error!");
return -1;
}
printf("socket ok!\n");
//绑定地址信息
int ret = bind(servFd, (struct sockaddr *)&servAddr, sizeof(servAddr));
if(ret < 0)
{
perror("bind error!");
close(servFd);
return -1;
}
printf("bind ok!\n");
//创建监听队列
ret = listen(servFd, 10);
if(ret < 0)
{
perror("listen error!");
close(servFd);
return -1;
}
printf("listening.....\n");
while(1)
{
//接收连接请求
int connFd = accept(servFd, NULL, NULL);
if(connFd < 0)
{
perror("accept error!");
close(servFd);
return -1;
}
printf("accept ok!\n");
pthread_t th;
while(pthread_create(&th, NULL, threadFunc, &connFd) < 0);
}
//关闭套接字
close(servFd);
return 0;
}
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
void*threadFunc(void*arg)
{
intconnFd=*((int*)arg);
charbuf[1024]={0};
while(1)
{
memset(buf,0,sizeof(buf));
//接收消息
intret=recv(connFd,buf,sizeof(buf),0);
if(ret<0)
{
perror("recv error!");
close(connFd);
pthread_exit((void*)-1);
}
elseif(0==ret)
{
printf("client shutdown!\n");
break;
}
printf("recv from client: %s\n",buf);
memset(buf,0,sizeof(buf));
printf("server:");
gets(buf);
send(connFd, buf, sizeof(buf), 0);
}
close(connFd);
pthread_exit(NULL);
}
int main()
{
//定义结构体变量,作为bind函数的参数
struct sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = PF_INET;
servAddr.sin_port = htons(8888);
servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//创建套接字
//返回值为新创建的socket的文件描述符,失败-1
int servFd = socket(PF_INET, SOCK_STREAM, 0);
if(servFd < 0)
{
perror("socket error!");
return -1;
}
printf("socket ok!\n");
//绑定地址信息
int ret = bind(servFd, (struct sockaddr *)&servAddr, sizeof(servAddr));
if(ret < 0)
{
perror("bind error!");
close(servFd);
return -1;
}
printf("bind ok!\n");
//创建监听队列
ret = listen(servFd, 10);
if(ret < 0)
{
perror("listen error!");
close(servFd);
return -1;
}
printf("listening.....\n");
while(1)
{
//接收连接请求
int connFd = accept(servFd, NULL, NULL);
if(connFd < 0)
{
perror("accept error!");
close(servFd);
return -1;
}
printf("accept ok!\n");
pthread_t th;
while(pthread_create(&th, NULL, threadFunc, &connFd) < 0);
}
//关闭套接字
close(servFd);
return 0;
}
客户端代码:
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
intmain()
{
//定义结构体变量,该变量保存的服务器的地址信息,作为connect的参数
structsockaddr_inservAddr;
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family=PF_INET;
servAddr.sin_port=htons(8888);
servAddr.sin_addr.s_addr=inet_addr("127.0.0.1");
//创建套接字
intcliFd=socket(PF_INET,SOCK_STREAM,0);
if(cliFd<0)
{
perror("socket error!");
return-1;
}
printf("socket ok!\n");
//发起连接请求
intret=connect(cliFd,(structsockaddr*)&servAddr,sizeof(servAddr));
if(ret<0)
{
perror("connect error!");
close(cliFd);
return-1;
}
printf("connect ok!\n");
charbuf[1024];
while(1)
{
memset(buf,0,sizeof(buf));
printf("client:");
gets(buf);
if(0==strcmp(buf,"quit"))
{
break;
}
//发送消息
ret=send(cliFd,buf,sizeof(buf),0);
if(ret<0)
{
perror("send error!");
close(cliFd);
return-1;
}
printf("send ok!\n");
memset(buf,0,sizeof(buf));
recv(cliFd,buf,sizeof(buf),0);
printf("recv from server %s\n",buf);
}
//关闭套接字
close(cliFd);
return0;
}
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
intmain()
{
//定义结构体变量,该变量保存的服务器的地址信息,作为connect的参数
structsockaddr_inservAddr;
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family=PF_INET;
servAddr.sin_port=htons(8888);
servAddr.sin_addr.s_addr=inet_addr("127.0.0.1");
//创建套接字
intcliFd=socket(PF_INET,SOCK_STREAM,0);
if(cliFd<0)
{
perror("socket error!");
return-1;
}
printf("socket ok!\n");
//发起连接请求
intret=connect(cliFd,(structsockaddr*)&servAddr,sizeof(servAddr));
if(ret<0)
{
perror("connect error!");
close(cliFd);
return-1;
}
printf("connect ok!\n");
charbuf[1024];
while(1)
{
memset(buf,0,sizeof(buf));
printf("client:");
gets(buf);
if(0==strcmp(buf,"quit"))
{
break;
}
//发送消息
ret=send(cliFd,buf,sizeof(buf),0);
if(ret<0)
{
perror("send error!");
close(cliFd);
return-1;
}
printf("send ok!\n");
memset(buf,0,sizeof(buf));
recv(cliFd,buf,sizeof(buf),0);
printf("recv from server %s\n",buf);
}
//关闭套接字
close(cliFd);
return0;
}
>>>IO多路复用的并发服务器
适合于客户端数量较多,但是短连接的情况。
适合于客户端数量较多,但是短连接的情况。
阅读全文
0 0
- TCP-网络服务器模型
- TCP网络服务器模型
- 网络编程之tcp服务器/客户端模型
- TCP服务器模型
- TCP服务器模型
- TCP客户/服务器模型
- TCP/IP网络模型
- tcp网络服务器程序
- note-网络-TCP-服务器
- 七、Linux网络编程-TCP客户/服务器模型、回射客户/服务器
- UDP-网络服务器模型
- linux网络服务器模型
- 多路复用服务器网络模型
- 网络并发服务器模型
- linux网络服务器模型
- linux网络服务器模型
- linux网络服务器模型
- linux网络服务器模型
- Spring 的骨骼架构
- 华为机试——取近似值
- Java基础知识点1
- 再论C语言指针、地址、赋值的问题,又是一通“扯”
- (2)没听说过这些,就不要说你懂并发了
- TCP网络服务器模型
- ACM 扫描法 Wine trading in Gergovia
- spring mvc
- Material Design 系列(2)—CoordinatorLayout,协调者布局
- Qt使用的一些技巧(未完待续。。。)
- NYOJ 14-会场安排问题(贪心)
- Java_基础—字节数组拷贝之available()方法
- 运输层协议TCP和UDP
- HDU