A simple class to do line-based TCP communication. To be used with the NetServicesMin library-.
Embed:
(wiki syntax)
Show/hide line numbers
tcplinestream.cpp
00001 /* 00002 * TcpLineStream library 00003 * Copyright (c) 2010 Hendrik Lipka 00004 * 00005 * Permission is hereby granted, free of charge, to any person obtaining a copy 00006 * of this software and associated documentation files (the "Software"), to deal 00007 * in the Software without restriction, including without limitation the rights 00008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00009 * copies of the Software, and to permit persons to whom the Software is 00010 * furnished to do so, subject to the following conditions: 00011 * 00012 * The above copyright notice and this permission notice shall be included in 00013 * all copies or substantial portions of the Software. 00014 * 00015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00021 * THE SOFTWARE. 00022 */ 00023 00024 #include "Timer.h" 00025 00026 #include "tcplinestream.h" 00027 00028 #include "dnsresolve.h" 00029 00030 void TCPLineStream::onTCPSocketEvent(TCPSocketEvent e) { 00031 // printf("New TCPSocketEvent: %d\n",e); 00032 switch (e) { 00033 case TCPSOCKET_CONNECTED: 00034 _connected = true; 00035 _connecting=false; 00036 break; 00037 00038 case TCPSOCKET_READABLE: 00039 break; 00040 case TCPSOCKET_WRITEABLE: 00041 break; 00042 00043 case TCPSOCKET_CONTIMEOUT: 00044 case TCPSOCKET_CONRST: 00045 case TCPSOCKET_CONABRT: 00046 case TCPSOCKET_ERROR: 00047 case TCPSOCKET_DISCONNECTED: { 00048 // don't close the real socket here, as this may skip the already received data 00049 _connected = false; 00050 _connecting=false; 00051 } 00052 break; 00053 } 00054 } 00055 00056 TCPLineStream::TCPLineStream(const char *server, int port, const char* term) { 00057 _server=server; 00058 _port=port; 00059 _term=term; 00060 } 00061 00062 bool TCPLineStream::open() { 00063 _closed=false; 00064 _readpos=0; 00065 _readlen=0; 00066 00067 _socket=new TCPSocket(); 00068 _socket->setOnEvent(this,&TCPLineStream::onTCPSocketEvent); 00069 00070 IpAddr addr; 00071 // ignore IP adress - is !null even if it is 0.0.0.0 00072 // so do DNS if a name is given 00073 if (NULL!=_server) { 00074 // printf("do DNS request for %s\n",_server); 00075 DNSResolver dr; 00076 addr=dr.resolveName(_server); 00077 } 00078 // printf("server=%i.%i.%i.%i/%i\n",addr[0],addr[1],addr[2],addr[3],_port); 00079 00080 Host host(addr, _port); 00081 00082 // printf("connect\n"); 00083 TCPSocketErr bindErr = _socket->connect(host); 00084 00085 if (bindErr != 0) { 00086 printf("connection bind error %i\n", bindErr); 00087 return false; 00088 } 00089 // printf("connecting\n"); 00090 // wait for connection established 00091 _connecting=true; 00092 mbed::Timer tmr; 00093 tmr.start(); 00094 tmr.reset(); 00095 00096 while (_connecting) { 00097 Net::poll(); 00098 wait_us(100); 00099 if (tmr.read()>20) { 00100 printf("error: reached timeout\n"); 00101 break; 00102 } 00103 } 00104 if (!_connected) { 00105 printf("error - could not connect (timeout)\n"); 00106 return false; 00107 } 00108 // printf("connected\n"); 00109 return true; 00110 } 00111 00112 void TCPLineStream::sendLine(string line) { 00113 // printf("send request[%s]\n",line.c_str()); 00114 _socket->send(line.append(_term).c_str(),line.length()+strlen(_term)); 00115 Net::poll(); 00116 } 00117 00118 void TCPLineStream::close() { 00119 if (_closed) 00120 return; 00121 00122 while (_connected) { 00123 Net::poll(); 00124 // read remaining data 00125 int err=_socket->recv(_readbuf,BUFSIZE-1); 00126 if (err<=0) 00127 break; 00128 } 00129 00130 while (true) { 00131 Net::poll(); 00132 // read remaining data 00133 int err=_socket->recv(_readbuf,BUFSIZE-1); 00134 if (err<=0) 00135 break; 00136 } 00137 00138 _socket->resetOnEvent(); 00139 _socket->close(); 00140 delete _socket; 00141 _closed=true; 00142 } 00143 00144 string TCPLineStream::readLine(int strLen) { 00145 string r; 00146 r.reserve(strLen); 00147 00148 int emptyCount=0; 00149 int lineendPos=0; 00150 while (true) { 00151 Net::poll(); 00152 if (_readlen>_readpos) { 00153 while (_readbuf[_readpos]!=0 && _readpos<_readlen) { 00154 char c=_readbuf[_readpos++]; 00155 //if the current char is the right one of the line terminator sequence 00156 if (c==_term[lineendPos]) { 00157 lineendPos++; 00158 if (0==_term[lineendPos]) { // last char of term sequence -> finished 00159 return r; 00160 } 00161 } else { // other characters 00162 int i=0; 00163 while (i<lineendPos) // add missed characters from term to string, if there are any 00164 r.push_back(_term[i++]); 00165 lineendPos=0; 00166 r.push_back(c); 00167 } 00168 } 00169 } else { 00170 int err=_socket->recv(_readbuf,BUFSIZE-1); 00171 if (err < 0) { 00172 printf("error while receiving data: %i!\n",err); 00173 break; 00174 } else if (err>0) { 00175 emptyCount=0; 00176 _readbuf[err]=0; 00177 _readlen=err; 00178 _readpos=0; 00179 // printf("r=%s\n",_readbuf); 00180 } else { 00181 // when we don't receive any data, and are not connected 00182 // we stop because there isn't anything left 00183 if (emptyCount++>2) 00184 if (!_connected) 00185 break; 00186 } 00187 } 00188 wait_us(100); 00189 } 00190 return r; 00191 } 00192
Generated on Sat Jul 16 2022 09:58:27 by 1.7.2