|
基于流模式的长连接我们可以做很多事情,比方说在局域网内,我们建立这种模式,可以时时传输数据,而不用每次传输数据是创建socket,传输完后,关闭socket。可以减少创建销毁socket的时间。
基于流模式的下,数据一直在发送,我们需要知道,每次发送数据量,所以常见的方式时,我们在发送数据时,指定此次发送数据的长度,服务器读取流数据时,先读取数据长度,然后再按长度读取此次发送的数据。
我使用select复用IO机制实现了一个简单的client,server机制,希望对初学者有帮助
客户端代码:
1./*
2. * ==================================================================
3. *
4. * Filename: client.cc
5. * Description:
6. * Version: 1.0
7. * Created: 2008年12月18日 09时50分36秒 CST
8. * Revision: none *
9. * Author: ugg (ugg_xchj@yahoo.com.cn)
10. * Company:
11. *
12. * ==================================================================
13. */
14.
15.#include <string>
16.#include <iostream>
17.#include <netdb.h>
18.#include <sys/socket.h>
19.#include <sys/types.h>
20.#include <netinet/in.h>
21.#include <arpa/inet.h>
22.
23.using namespace::std;
24.
25.// 默认内容设置
26.string hostname="localhost";
27.int hostport=7763;
28.string sendContents="this is client";
29.
30.void getCMD(int argc, char *argv[])
31.{
32. switch(argc)
33. {
34. case 2:
35. hostname = argv[1];
36. break;
37. case 3:
38. hostname = argv[1];
39. hostport = atoi(argv[2]);
40. if(hostport < 1024 || hostport >65535)
41. {
42. cerr << "Error: port=" << hostport
43. << " Error, range 1024 - 65535" << endl;
44. exit(0);
45. }
46. break;
47. case 4:
48. hostname = argv[1];
49. hostport = atoi(argv[2]);
50. if(hostport < 1024 || hostport >65535)
51. {
52. cerr << "Error: port=" << hostport
53. << " Error, range 1024 - 65535" << endl;
54. exit(0);
55. }
56. sendContents = argv[3];
57. break;
58. default:
59. break;
60. }
61.}
62.
63.int
64.main ( int argc, char *argv[] )
65.{
66. getCMD(argc,argv);
67.
68. int fd;
69. // create socket
70. if((fd=socket(PF_INET,SOCK_STREAM,0)) == -1)
71. {
72. cerr << "Error: socket()" <<endl;
73. exit(0);
74. }
75. //
76. struct hostent *he;
77. he = gethostbyname(hostname.c_str());
78. if(he == NULL ) {
79. cerr <<"Error: gethostbyname() error,hostname=" << hostname << endl;
80. exit(0);
81. }
82.
83. struct sockaddr_in serv_addr;
84.
85. serv_addr.sin_family=AF_INET;
86. serv_addr.sin_port=htons(hostport);
87. serv_addr.sin_addr=*((struct in_addr*)he->h_addr);
88. bzero( &(serv_addr.sin_zero),8);
89.
90. // connction
91. if(connect(fd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1) {
92. cerr<<"Error: connect() error"<<endl;
93. exit(0);
94. }
95.
96. cout << "send contents to server(" << hostname
97. << ":" << hostport << ")" << endl;
98. cout << sendContents << endl;
99. cout << "................" << endl;
100.
101. // 增加此次发送消息的长度
102. char buffer[1024];
103. sprintf(buffer,"%8d",sendContents.length());
104.
105. sendContents = string(buffer,8)+sendContents;
106.
107. const char* content = sendContents.c_str();
108. int send=0;
109. int length = sendContents.length();
110.
111. // send
112. while(1)
113. {
114. int ret = write(fd,content+send,length-send);
115. if(ret == 0)
116. {
117. // server close
118. cerr << "Error: server close" << endl;
119. exit(0);
120. }
121. send += ret;
122. if(length == send)
123. break;
124. }
125.
126. string contents;
127. // 先接受8字节,获取服务返回长度
128. int ret = recv(fd,buffer,8,0);
129. // 服务器关闭
130. if(ret == 0)
131. {
132. cerr << "Error: server close" << endl;
133. exit(0);
134. }
135. if(ret == 8)
136. {
137. buffer[8]='\0';
138. int len = atoi(buffer);
139. if(len < 1024){
140. int rets=0;
141. while((ret = recv(fd,buffer,len-rets,0))>0)
142. {
143. contents.append(buffer,ret);
144. rets += ret;
145. if(len==rets)
146. break;
147. }
148. }else{
149. int buflen=1024;
150. while( (ret = recv(fd,buffer,buflen,0)) > 0)
151. {
152. contents.append(buffer,ret);
153. len-=ret;
154. if(len<2048){
155. buflen=len;
156. }
157. if(len <= 0)
158. break;
159. }
160. }
161. }else {
162. cerr << "Error: recv data Error " << endl;
163. }
164.
165. cout << "recv: ";
166. cout << contents << endl;
167.
168. return 0;
169.} /* ---------- end of function main ---------- */
|
|