TCP/IP Problem

2014-08-05
2014-08-08
  • steve williams

    steve williams - 2014-08-05

    This is probably not a GNU COBOL problem, but you have been helpful in the past so I thought I'd ask.

    problem 1) The following TCP/IP client fails at the call 'connect' step. The TCP/IP server is running and responds correctly to a mozilla client request.

    problem 2) ERRNO doesn't seem to work in the client.

    Similar code on other machines (big endian) works.

    Steve Williams


    1) The platform: Ubuntu 12.04 Lenovo 61i

    2) The test TCP/IP Server program (taken directly from Beazley)

    #!/usr/bin/python2.7
    import SocketServer
    import socket
    import string
    # Read an HTTP request from a cient and bounce it back in a web page
    class EchoHandler(SocketServer.BaseRequestHandler):
        def handle(self):
            f = self.request.makefile()
            self.request.send("HTTP/1.0 200 OK\r\n")
            self.request.send("Content-type: text/plain\r\n\r\n")
            self.request.send("Received connection from %s\r\n\r\n" % (self.client_address,))
            while 1:
                line = f.readline()
                self.request.send(line)
                if not string.strip(line):
                    break
            f.close()
    # create the server and start serving
    print 'start tcpserver'
    serv = SocketServer.TCPServer(("127.0.0.1",8080),EchoHandler)
    serv.serve_forever()
    print 'end tcpserver'
    

    3) The GNU Cobol compiler

    cobc (OpenCOBOL) 2.0.0
    Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Keisuke Nishida
    Copyright (C) 2006-2012 Roger While
    This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    Built Oct 10 2013 16:15:17
    Packaged Feb 11 2012 12:36:31 UTC
    C version "4.6.3"

    4) The failing TCP/IP Client

              >>SOURCE FORMAT FREE
    identification division.
    program-id. tcpipclient.
    
    environment division.
    configuration section.
    repository. function all intrinsic.
    
    data division.
    working-storage section.
    01 ERRNO external pic 9(8) comp.
    
    01 socket-descriptor pic 9(8) comp.
    
    01 socket-address.
       03  socket-port pic 9(8) comp.
       03  filler redefines socket-port.
           05  socket-family pic 9(4) comp.
           05  filler pic 9(4) comp.
       03  socket-ipaddress pic s9(8) comp.
       03  filler pic x(8) value low-values.
    
    01 AF_INET pic 9(4) value 2.
    01 SOCK_STREAM pic 9(4) value 1.
    01 port-value pic s9(4) comp.
    
    01 new-line pic x value x'0A'.
    
    procedure division.
    start-tcpipclient.
    
        display new-line 'call socket' end-display
        call 'socket' using by value AF_INET, by value SOCK_STREAM, 0 end-call
        if return-code = -1
            display "call 'socket' failed" end-display
            display errno ' = errno' end-display
            stop run
        end-if
        move return-code to socket-descriptor
        display socket-descriptor ' = socket-descriptor' end-display
    
        display new-line 'call htons' end-display
        move 8080 to port-value
        call 'htons' using by value port-value
        display return-code ' = htons return-code' end-display
        move return-code to socket-port
        display socket-port ' = socket-port'
    
        move AF_INET to socket-family
    
        display new-line 'call inet_addr' end-display
        call 'inet_addr' using by content '127.0.0.1'
        move return-code to socket-ipaddress
        display socket-ipaddress ' = socket-ipaddress' end-display
    
        display new-line 'call connect' end-display
        move 1 to errno
        call 'connect' using by value socket-descriptor by reference socket-address by value length(socket-address) end-call
        if return-code <> 0
            display "call 'connect' failed" end-display
            display return-code ' = return-code' end-display
            display errno ' = errno' end-display
            stop run
        end-if
    
        call 'close' using by value socket-descriptor end-call
        display 'end tcpipclient' end-display
    
        stop run
        .
    end program tcpipclient.
    
     
    Last edit: Simon Sobisch 2014-08-05
  • Klaus Schäfer

    Klaus Schäfer - 2014-08-05

    I use the EZASOKET-Library from coders.google.com and it works like the EZASOKET- Call from IBM Enterprise-Cobol without any problems. I portet some Network-Programs from Z/OS to Linux and using the EZASOKET-Library I had nothing to change in the sourcecode and it worked as expected. What Library do you use for the Network-calls ?

     
  • Simon Sobisch

    Simon Sobisch - 2014-08-05

    Please add information how the CALL to 'connect' fails (return-code/errno). From all information given the vars of socket-address may not defined correct (as this is the only thing you pass by reference).

    Simon

     
  • steve williams

    steve williams - 2014-08-05

    Simon,

    Thanks for your reply.

    The call 'connect' return-code value is -1. (I think that's the only possible error code, the rest of the information is usually in ERRNO). ERRNO value is the preset value 1. Not much help. I've tried ERRNO upper case and lower case. ERRNO external works on bigendian machines with (much) older COBOL compilers.

    The fields in socket address are a little strange in my example. I use a 32-bit value for socket-port and a redefines for socket-family because some port values can exceed 9999 so socket-port pic 9(4) comp will truncate -- I think little-endian/big-endian might be a problem here. I've tried the code with and without a call to 'htons'. I know I'm avoiding usage binary.

    Klaus,

    Thank you for your reply. I'm using whatever Ubuntu 12.04/Linux provides as my library. Here I'm trying to avoid third party libraries -- trying to do it all in GNU COBOL 2.0 and the available software. An experiment, if you will.

    Steve Williams

     
  • Brian Tiffin

    Brian Tiffin - 2014-08-06

    Side note:

    Anyone needing access to ERRNO, see http://opencobol.add1tocobol.com/gnucobol/#errno

    It's accessed from C, and all it takes is adding geterrno.c to compile lines (or whatever you call the sources with a few lines of C to get at the external errno).

    Cheers,
    Brian

     
    • Simon Sobisch

      Simon Sobisch - 2014-08-06

      Topic drift: I propose new system routine for this, maybe CBL_OC_ERRNO with passed 0 (reset errno) or 1 (errno is returned in return-code). @Brian: Sounds like something for you, don't it? I'm open for a commit to 2.0 branch (as long as a useful test case is included).

      Simon

       
      • Brian Tiffin

        Brian Tiffin - 2014-08-07

        +1, will look at coding this up.

        There are a few extern variables in C space that could use a routine like this. errno, stdscr, (well, actually, stdin, stdout, stderr (as FILE *) and some others.

        Cheers,
        Brian

         
  • Anonymous - 2014-08-07

    Simon, Brian,

    Thank you for your help.

    I replaced all the pic ... comp definitions with binary-int unsigned and binary-short unsigned and the call 'connect' now works.

    I do like accessing ERRNO in cobol or a cobol intrinsic. Not that I don't like c, but I do like cobol.

    Steve Williams

     
    • Simon Sobisch

      Simon Sobisch - 2014-08-07

      Hi Steve, please drop a short sample (for example a server with two clients connecting) when you're finished.

      Simon

       
  • steve williams

    steve williams - 2014-08-08

    Simon,

    Thank you for your interest. I intend to create a suite of COBOL 2.0 programs called something like 'Fun With Sockets' -- TCP/IP, UDP, REST, cross-platform scheduling and process activation, pushing and pulling data, etc, etc. This was one of the first attempts.

    Steve Williams

     


Anonymous

Cancel  Add attachments