服务器模型

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

在网络通信过程中,服务端通常需要处理多个客户端。由于多个客户端的请求可能会同时到来,服务器端可采用不同的方法来处理。总体上来说,服务器端可采用两种模型来实现:循环服务器模型和并发服务器模型。

循环服务器模型是指服务器端依次处理每个客户端,直到当前客户端的所有请求处理完毕,再处理下一个客户端。这类模型的优点是简单,缺点显而易见。特别是TCP循环服务器模型,由于必须先处理完当前客户端,容易造成其他客户端等待时间较长的情况。

为了提高服务器的并发处理能力,又引入了并发服务器模型。其基本思想是在服务器端此阿勇多任务机制(多进程或多线程),分别为每个客户端创建一个任务来处理,极大地提高了服务器的并发处理能力。

下面具体介绍循环服务器模型和并发服务器模型的流程及实现。为了更好的进行对比。本节均以TCP为例讨论相关模型。

一、循环服务器(TCP)

1、运行介绍

TCP循环服务器是一种常用的模型,其工作流程如下:

1)服务器端从连接请求队列中提取请求,建立连接并返回新的已连接套接字;

2)服务器端通过已连接套接字循环接收数据,处理并发送给客户端,知道客户端关闭连接;

3)服务器端关闭已连接套接字,返回步骤1;

2、特点分析

通过上面对服务器执行过程的介绍,可以得到以下结论。

1)服务器端采用循环嵌套来实现。外层循环依次提取每个客户端的连接请求,建立TCP连接。内层循环接受并处理当前客户端的所有数据,知道客户端关闭连接;

2)如果当前客户端没有处理结束,其他客户端必须一直等待。

注意:采用这种模型的服务器无法同时为多个客户端服务。

3、编程示例

下面实现TCP ECHO 服务器端和客户端。服务器端接收到客户端数据后,原封不动发送回去(回射服务);客户端运行时,用户从键盘输入字符串,发送给服务器端并接受返回的数据,直到用户输入quit 后退出。

server.c

[cpp]view plain copy

1.#include

2.#include

3.#include

4.#include

5.#include

6.#include

7.#include

8.#include

9.#define BUFFER_SIZE 128

10.#define PORT 8888

11.

12.int main()

13.{

14.int listenfd, clientfd;

15.int n;

16.struct sockaddr_in serveraddr,clientaddr;

17. socklen_t peerlen;

18.char buffer[BUFFER_SIZE];

19.

20.if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)

21. {

22. perror("socket error");

23. exit(-1);

24. }

25.else

26. {

27. printf("listenfd:%d\n",listenfd);

28. }

29.

30. memset(&serveraddr,0,sizeof(serveraddr));

31. serveraddr.sin_family = AF_INET;

32. serveraddr.sin_port = htons(PORT);

33. serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

34.

35.if(bind(listenfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)) < 0) //绑定IP地址和端口号

36. {

37. perror("bind error");

38. exit(-1);

39. }

40.else

41. {

42. printf("bind successfully!\n");

43. }

44.

45.if(listen(listenfd,10) == -1)

46. {

47. perror("listen error");

48. exit(-1);

49. }

50.else

51. {

52. printf("listening....\n");

53. }

54.

55. peerlen = sizeof(clientaddr);

56.while(1)

57. {

58.if((clientfd = accept(listenfd,(struct sockaddr *)&clientaddr,&peerlen)) < 0) //循环等待客户端的连

59. {

60. perror("accept error");

61. exit(-1);

62. }

63.else

64. {

65. printf("connection from [%s:%d]\n",inet_ntoa(clientaddr.sin_addr)

66. ,ntohs(clientaddr.sin_port));

67. }

68.

69. memset(buffer,0,sizeof(buffer));

70.while(1)

71. {

72.if((n = recv(clientfd,buffer,BUFFER_SIZE,0)) == -1) //循环接收客户端发送的数据

73. {

74. perror("recv error");

75. exit(-1);

76. }

77.else if(n == 0) //此时,客户端断开连接

78. {

79.break;

80. }

81.else

82. {

83. printf("Received message:%s\n",buffer);

84.if(send(clientfd, buffer, n, 0) == -1)

85. {

86. perror("send error");

87. exit(-1);

88. }

89.else

90. {

91. printf("sendmessage:%s\n",buffer);

92. }

93. }

94. }

95. close(clientfd); //客户端断开连接后,服务端也断开

96. }

97. close(listenfd);

98.

99.return 0;

100.}

client.c

[cpp]view plain copy

相关文档
最新文档