Hi Mangesh, On Wed, Feb 20, 2013 at 10:47:16AM +0000, Shukla, Mangesh wrote: > Hi Ariel, Based on your suggestion below, I have implemented a Socket > server in my external application dll , and now listen to it on > a different port than the one that it connects with OOo. I have been > able to connect with it from the OOBasic macro function. I am even > able to send across a string to the external application using the > socket connection. However I am facing some issues which I have > posted on the openoffice forum. Could you please have a look and let > me know if you have any suggestions to make it work. > > http://forum.openoffice.org/en/forum/viewtopic.php?f=44&t=59806
Unless there is a typo, there is an error in the macro nBytesRead = oConnection.read()(aByteArray, 200) read() takes two arguments, you have read()(ByteArray, 200) You should be aware that read() blocks until it reads the amount you specify or the connection in closed. If your socket server writes 100, the macro will wait for other 100. On the socket code, the logic for reading looks wrong too: read(buffer, 256) will return after 256 bytes are read, or the connection is closed. With the exception thrown due to your Basic code, the connection gets closed by the clean-up performed by the OOo Basic engine, that's why it returns; but if the macro writes 200 bytes, read() will wait for the remaining 6. You better use recv, that tries to read up to some bytes, and you should read in a loop (if your buffer is 256 and the peer writes 300, the first recv will return 256, the second recv will return 44, -1 on error, and 0 when the peer closed the connection). Unfortunately, in AOO API the connector uses internally only read(), this means that unless you will read/write in a fixed size, you will need to use another language, and not AOO API, but the tools provided by that language. http://opengrok.adfinis-sygroup.org/source/xref/aoo-trunk/main/io/source/connector/ctr_socket.cxx#127 (Side note, flush() does nothing, obviously it does not make sense when they use read/write) Another point, your socket server should be accepting on its own thread, otherwise acceptConnection() will block your application. Attached is a dummy, untested example. It accepts only one connection at the time, and after reading the first peer's write, it closes the connection (for something more realistic, you'll need a multi-threaded server - I'd use boost::asio instead of AOO C++ language binding). Regards -- Ariel Constenla-Haile La Plata, Argentina
/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ #include <sal/main.h> #include <osl/file.hxx> #include <osl/thread.hxx> #include <osl/thread.h> #include <osl/socket.hxx> #include <rtl/ustring.hxx> #include <rtl/ustrbuf.hxx> #include <iostream> #include <cstring> #define DEFAULT_PORT 2042 using rtl::OUString; using namespace std; using namespace osl; class AcceptorThread : public osl::Thread { public: AcceptorThread( ); ~AcceptorThread( ); void run( ); void terminate( ); bool isValid( ) { return m_bValid; } sal_Int32 getPort( ) { return m_aAddress ? m_aAddress->getPort( ) : -1; } private: void bind( ); void listen( ); AcceptorSocket *m_aSocket; SocketAddr *m_aAddress; bool m_bValid; sal_Bool m_bListening; }; AcceptorThread::AcceptorThread( ) : m_aSocket( 0 ) , m_aAddress( 0 ) , m_bValid( false ) , m_bListening( sal_False ) { OSL_TRACE( "AcceptorThread::AcceptorThread" ); bind( ); } AcceptorThread::~AcceptorThread( ) { OSL_TRACE( "AcceptorThread::~AcceptorThread" ); delete m_aSocket; delete m_aAddress; } void AcceptorThread::run( ) { OSL_TRACE( "AcceptorThread::run" ); listen( ); } void AcceptorThread::terminate( ) { OSL_TRACE( "AcceptorThread::terminate" ); if ( m_aSocket ) { m_bListening = sal_False; m_aSocket->close( ); } Thread::terminate( ); } void AcceptorThread::bind( ) { OSL_TRACE( "AcceptorThread::bind" ); sal_Int32 port = DEFAULT_PORT; m_bValid = false; m_aAddress = new SocketAddr( OUString( RTL_CONSTASCII_USTRINGPARAM( "localhost" ) ), port ); if ( !m_aAddress->is( ) ) { cerr << " There was an error in creating the SocketAddr \n"; return; } m_aSocket = new AcceptorSocket( ); if ( m_aSocket == 0 ) { cerr << "error creating a socket\n"; return; } while ( !( m_bValid = m_aSocket->bind( *m_aAddress ) ) ) { m_aAddress->setPort( ++port ); } } void AcceptorThread::listen( ) { OSL_TRACE( "AcceptorThread::listen" ); if ( !isValid() ) return; StreamSocket aConnection; oslSocketResult socketResult; sal_Int32 nTotalBytes = 255; sal_Char buffer[nTotalBytes]; sal_Int32 nTotalBytesRead, nRead; rtl::OUStringBuffer aBuffer; // number of connections at a time m_bListening = m_aSocket->listen( 5 ); while ( isRunning( ) && m_bListening ) { socketResult = m_aSocket->acceptConnection( aConnection ); if ( socketResult != osl_Socket_Ok ) { if ( !isRunning( ) || !m_bListening ) { cout << "Not running... Stop accepting.\n"; break; } cerr << " There was an error in accepting connection: " << rtl::OUStringToOString( aConnection.getErrorAsString( ), osl_getThreadTextEncoding() ).getStr( ) << '\n'; continue; } cout << "Received request from " << rtl::OUStringToOString( aConnection.getPeerHost(), osl_getThreadTextEncoding() ).getStr() << ':' << aConnection.getPeerPort() << '\n'; // request do { memset( buffer, '\0', nTotalBytes ); nRead = aConnection.recv( buffer, nTotalBytes, osl_Socket_MsgNormal ); if ( nRead > 0 ) { nTotalBytesRead += nRead; aBuffer.appendAscii( buffer, nRead ); } } while ( nRead == nTotalBytes ); cout << "Received " << nTotalBytesRead << " bytes\n"; nTotalBytesRead = 0; OUString aString = aBuffer.makeStringAndClear( ); rtl::OString aStr = rtl::OUStringToOString( aString, osl_getThreadTextEncoding() ); cout << "Content received:\n" << aStr.getStr( ); // response sal_Int32 nWrite = aStr.getLength( ); sal_Int32 n = aConnection.write( aStr.getStr( ), nWrite ); if ( n != nWrite ) { cerr << "error writing to socket\n"; } aConnection.close( ); } } SAL_IMPLEMENT_MAIN_WITH_ARGS( argc, argv ) { AcceptorThread test; if ( !test.isValid( ) || !test.create( ) ) return 1; cout << "Listening on port " << test.getPort( ) << '\n'; cout << "Press ENTER to terminate listening..."; cin.get( ); test.terminate( ); cout << "Press ENTER to exit..."; cin.get(); return 0; }
pgpcPMePrRW70.pgp
Description: PGP signature