程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 基於流模式長連接的簡單實現

基於流模式長連接的簡單實現

編輯:關於C++

基於流模式的長連接我們可以做很多事情,比方說在局域網內,我們建立這種模式,可以時時傳輸數據,而不用每次傳輸數據是創建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 ([email protected])
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  ---------- */

服務器端代碼

1./*
2. * =====================================================================================
3. *
4. *       Filename:  server.cc
5. *    Description:  
6. *        Version:  1.0
7. *        Created:  2008年12月18日 09時50分50秒 CST
8. *       Revision:  none *
9. *         Author:  ugg ([email protected])
10. *        Company:  
11. *
12. * =====================================================================================
13. */
14.#include <string>
15.#include <iostream>
16.#include <netdb.h>
17.#include <sys/socket.h>
18.#include <sys/types.h>
19.#include <netinet/in.h>
20.#include <arpa/inet.h>
21.#include <errno.h>
22.#include <map>
23.
24.using namespace::std;
25.
26.struct clientInfo
27.{
28.    string host;
29.    int port;
30.};
31.
32.typedef map<int, clientInfo> mapgroups;
33.typedef map<int, clientInfo>::iterator mapgroupsor;
34.typedef map<int, clientInfo>::const_iterator mapgroupscor;
35.
36.//  記錄客戶端的信息
37.mapgroups groups;
38.
39.// 默認內容設置
40.string hostname="localhost";
41.int    hostport=7763;
42.string serversendContents="this is server";
43.44.void getCMD(int argc, char *argv[])
45.{
46.    switch(argc)
47.    {
48.        case 2:
49.            hostname = argv[1];
50.           break;
51.        case 3:
52.            hostname = argv[1];
53.            hostport = atoi(argv[2]);   
54.            if(hostport < 1024 || hostport >65535)
55.            {
56.                cerr << "Error: port=" << hostport 
57.                    << " Error, range 1024 - 65535" << endl;
58.                exit(0);
59.            }
60.            break;
61.        case 4:
62.            hostname = argv[1];
63.            hostport = atoi(argv[2]);   
64.            if(hostport < 1024 || hostport >65535)
65.            {
66.                cerr << "Error: port=" << hostport 
67.                    << " Error, range 1024 - 65535" << endl;
68.                exit(0);
69.            }
70.            serversendContents = argv[3];   
71.            break;
72.        default:
73.            break;
74.    }
75.}   
76.
77.void clearfd(int fd,fd_set& rdfds)
78.{
79.    FD_CLR(fd,&rdfds);  
80.    mapgroupsor it = groups.find(fd);
81.    if(it != groups.end())
82.    {
83.        cerr << "client host=" << it->second.host << ", port=" << it->second.port 
84.            << " close" << endl;
85.        groups.erase(fd);
86.    }
87.}
88.
89.// recv and send message
90.void recvandsend(int fd,fd_set& rdfds,string& contents, const string& texts)
91.{
92.    // 接受消息
93.    char buffer[1024];
94.    int rets=0;
95.    int ret=0;
96.    ret = recv(fd,buffer,8,0);
97.
98.    if(ret == 0)
99.    {
100.        clearfd(fd,rdfds);
101.        return;
102.    }
103.    if(ret == 8)
104.    {
105.        buffer[8]='\0';
106.        int len = atoi(buffer);
107.        if(len < 1024){
108.            while((ret = recv(fd,buffer,len,0))>0)
109.            {
110.                contents.append(buffer,ret);
111.                rets += ret;
112.                len-=ret;
113.                if(len==0)
114.                    break;
115.            }
116.            if(ret == 0){
117.                clearfd(fd,rdfds);
118.                return;
119.            }
120.        }else{
121.            int buflen=1024;
122.            while( (ret = recv(fd,buffer,buflen,0)) > 0)
123.            {
124.                contents.append(buffer,ret);
125.                rets += ret;
126.                len-=ret;
127.                if(len<2048){
128.                    buflen=len;
129.                }
130.                if(len <= 0)
131.                    break;
132.            }
133.            if(ret == 0){
134.                clearfd(fd,rdfds);
135.                return;
136.            }
137.        }
138.    }else{
139.        clearfd(fd,rdfds);
140.        return;
141.    }
142.
143.    // 發送信息
144.    sprintf(buffer,"%8d",texts.length());   
145.    string sendContents = string(buffer,8);
146.    sendContents += texts;
147.
148.    const char* content = sendContents.c_str();
149.    int send=0;
150.    int length = sendContents.length();
151.
152.    // send
153.    while(1)
154.    {
155.        int ret = write(fd,content+send,length-send);
156.        if(ret == 0)
157.        {
158.            // server close
159.            cerr << "Error: server close" << endl;
160.            clearfd(fd,rdfds);
161.            return;
162.        }
163.        send += ret;
164.        if(length == send)
165.            break;
166.    }
167.}   
168.
169.int
170.main ( int argc, char *argv[] )
171.{
172.    getCMD(argc,argv);
173.    
174.    int fd; 
175.    // create socket
176.    if((fd=socket(PF_INET,SOCK_STREAM,0)) == -1)
177.    {
178.        cerr << "Error: socket()" <<endl;
179.        exit(0);
180.    }
181.    //
182.    struct hostent *he;
183.    he = gethostbyname(hostname.c_str());
184.    if(he == NULL ) {
185.        cerr <<"Error: gethostbyname() error,hostname=" << hostname << endl;
186.        exit(0);
187.    }
188.
189.    struct sockaddr_in serv_addr;
190.
191.    serv_addr.sin_family=AF_INET;
192.    serv_addr.sin_port=htons(hostport);
193.    serv_addr.sin_addr=*((struct in_addr*)he->h_addr);
194.    bzero( &(serv_addr.sin_zero),8);
195.
196.    // bind
197.    if(bind(fd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1) {
198.        cerr<<"Error: bind() error"<<endl;
199.        exit(0);
200.    }
201.
202.    // listen
203.    int ret_listen = listen(fd,5);
204.    if(ret_listen < 0)
205.    {
206.        cerr << "Error: Listen port error,socket fd: " << fd << endl;
207.        cerr << "Error: listen errno = " << ret_listen << endl;
208.        exit(0);
209.    }
210.
211.    fd_set rdfds;
212.    int nfds;
213.
214.    // First poll the sockets
215.    FD_ZERO(&rdfds);
216.    FD_SET(fd, &rdfds);
217.    while(1)
218.    {
219.        if ((nfds = select(FD_SETSIZE, &rdfds, NULL, NULL, NULL)) < 0) {
220.            if (errno != EINTR) {
221.                cerr << "Error: select error" << endl;

222.                exit(3);
223.            }
224.        }
225.
226.        if(FD_ISSET(fd, &rdfds))
227.        {
228.            socklen_t len;
229.            struct sockaddr_in client_addr;
230.            len = sizeof(struct sockaddr);
231.            int clientfd = accept(fd,(struct sockaddr *)&client_addr,&len);
232.            if(clientfd == -1)
233.            {
234.                cerr << "Error: accept client error" << endl;
235.            }else{
236.                clientInfo info;    
237.                info.host = inet_ntoa(client_addr.sin_addr);
238.                info.port = ntohs(client_addr.sin_port);
239.                cerr << "server: got connection from "<< info.host 
240.                    <<", port "<< info.port << endl;
241.                groups.insert(make_pair(clientfd,info));
242.                FD_SET(clientfd,&rdfds);
243.            }
244.        }else{
245.            mapgroupscor it;
246.            for(it = groups.begin(); it != groups.end(); ++it)
247.            {
248.                if(FD_ISSET(it->first,&rdfds))
249.                {
250.                    string strRev;
251.                    recvandsend(it->first,rdfds,strRev,serversendContents);         
252.                    break;
253.                }
254.            }
255.        }
256.
257.    }   
258.
259.    return 0;
260.}               /* ----------  end of function main  ---------- */
261.

上面的代碼在linux下已經編譯通過

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved