B4J Question TCP Send string

Pedro Caldeira

Active Member
Licensed User
Longtime User
Hello,
I am writing a simple non-ui application to send a string to a socket port and get the result.
I always receive a timeout error, but when sending direclty to port (linux) the service on the other side, answers.
What am i doing wrong !?

B4X:
Sub Process_Globals
    Dim AStreams As AsyncStreams
    Dim Socket1 As Socket
    Public SaleString As String = "4100000100"
End Sub

Sub AppStart (Args() As String)
 
 
    MainSub
    StartMessageLoop
 
End Sub

Sub MainSub
 
    Socket1.Initialize("icash")
    Socket1.Connect("192.168.0.203",10000,0)
 
End Sub

Sub icash_Connected(Successful As Boolean)

    If Successful = True Then
        AStreams.Initialize(Socket1.InputStream,Socket1.OutputStream,"AStream")
        sendMsg
    Else
        Log ("Error Connecting")
    End If

End Sub

Sub AStreams_NewData (Buffer() As Byte)
    Dim msg As String
    msg = BytesToString(Buffer, 0, Buffer.Length, "UTF8")
    Log(msg)
End Sub

Sub AStreams_Error
    Log("AStreams_Error")
End Sub

Sub AStreams_Terminated
    Log("AStreams_Terminated")
End Sub

Sub sendMsg
    Dim buffer() As Byte
    buffer = SaleString.GetBytes("UTF8")
    AStreams.Write(buffer)
    Log("Sending: " & SaleString)
End Sub

the result in debug window

B4X:
Waiting for debugger to connect...
Program started.
java.net.ConnectException: Connection timed out: connect
    at java.net.DualStackPlainSocketImpl.connect0(Native Method)
    at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at anywheresoftware.b4a.objects.SocketWrapper$1.run(SocketWrapper.java:140)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Error Connecting
 

OliverA

Expert
Licensed User
Longtime User
Socket1.Connect("192.168.0.203",10000,0)
Are you sure the IP (192.168.0.203) and the Port (10000) are correct? Screenshot of the Linux connection (with IP and Port)? Also what are you using on Linux to connect? What protocol? Telnet? Raw? Does the service block certain IP addresses (blacklist) or only accept certain IP addresses (whitelist)?

Edit: If you are running this on a Windows box, use putty (https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) to connect to the service and see what it takes to connect.
 
Upvote 0

Pedro Caldeira

Active Member
Licensed User
Longtime User
Yes, I am connected to the LAN, and the IP and Port are correct.

How can I send for instance a simple string "4100000100 " to 192.168.0.203 at port 10000
and receive the reply at port 11000.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
If the 11000 port is located on the same machine as port 10000, then just open another socket going to that port and initialize another asyncstream.

If the remote machine is trying to contact you on port 11000, then you will have to create a server socket, listen for an inbound connection, then assign the socket created for you to asyncstream.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Yes
 
Upvote 0

Pedro Caldeira

Active Member
Licensed User
Longtime User
I am trying a simple code, using sockets and AsynstreamText, and works great to send data.
My Question is :
Can I use the socket object to also read from the same ip and port, or do I always need to use a Serversocket to read data ?

B4X:
'Non-UI application (console / server application)
#Region Project Attributes
    #CommandLineArgs:192.168.0.203 10000 0 6000000000
    #MergeLibraries: True
#End Region

Sub Process_Globals
    Private SocketTCP As Socket
    Private IOStreams As AsyncStreamsText
    Private Ip_Address As String
    Private Port_Number As String
    Private Time_Out As String
    Private String2Send As String
  
    'Pay  = "4100000010"
    'Cancel = "6000000000"
    'Extradata = "00000000000000000000000"
End Sub

Sub AppStart (Args() As String)
  
    If Args.Length <> 4 Then
        Log("glory <IP Adress> <Port> <Timeout> <String>")
        ExitApplication2(0)
    End If
  
    Ip_Address=Args(0)
    Port_Number=Args(1)
    Time_Out=Args(2)
    String2Send=Args(3)
  
    SocketTCP.Initialize("SocketTCP")
    SocketTCP.Connect(Ip_Address,Port_Number,Time_Out)
    StartMessageLoop
End Sub

Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub


Sub SocketTCP_Connected(Successful As Boolean)
  
    If Successful = True Then
        IOStreams.Initialize(Me,"IOStreams",SocketTCP.InputStream,SocketTCP.OutputStream)
        SendData2Socket
    Else
        Log ("Not Connected")
    End If
  
End Sub

Sub SendData2Socket
  
    IOStreams.Write(String2Send)
    Log("Sending:" & String2Send & " to " & Ip_Address & ":" & Port_Number)
    ExitApplication2(0)
  
End Sub
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
In your sample above, the event routine
B4X:
sub IOStreams_NewData(Buffer() As Byte)
end sub
would receive the incoming data.

ServerSockets are only needed if you want your program to accept incoming connection requests. As your code stands right now, if another machine on the network (any network) wants to communicate with you, it could not, since you do not have a ServerSocket set up to allow incoming connections. All you did here is create a socket that connects to another machine. That other machine is set up to allow incoming connections. If you set up connections to another machine (after which you can read and write to that machine), sockets are all you need.

If you want to allow other machines to connect to you, then you need a ServerSocket. Once another machine connects to you (completes a TCP handshake, see http://www.inetdaemon.com/tutorials/internet/tcp/3-way_handshake.shtml), then the ServerSocket will create a regular socket that you can use to read and write to the machine that is connecting to you. This socket is given to you via the NewConnection event of the ServerSocket class. Beyond the TCP handshake, ServerSockets are not used to communicate with the other machine(s).

Hope this makes it clearer instead of murkier.
 
  • Like
Reactions: udg
Upvote 0

Pedro Caldeira

Active Member
Licensed User
Longtime User
Hello OliverA,
I have implemented the routine below, since I am using AsyncStreamTexts, but I am not getting any data

B4X:
Sub IOStreams_NewText(Text As String)
       Log (Text)
End Sub
 
Last edited:
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Upvote 0

OliverA

Expert
Licensed User
Longtime User
I am trying with the same port to read and write now.
And you should. From what I can tell, you're saying you can sent data to the 10000 port on the other machine, but your getting nothing back? That's not an issue with your socket, that is an issue with the other side not sending you any data. You mentioned something about port 11000. What's up with that port? Where did that number come from? It could be that you have to create a second socket connection to that port and listen to it to get your answer. I'm guessing here with the limited info you have given (about that other port - 11000)
 
Upvote 0

Pedro Caldeira

Active Member
Licensed User
Longtime User
The service has a configuration file where I can specifiy an address and a port for the service to send data.
I mentioned port 11000 because i had the config file configured in that way.
now, i do not, so all the reads and writes are on the same port.
The service sends the reply (or it should) to the same port and to the IP that write the data.
The problem is that I am not receiving it. I am going to place a packet sniffer in beetween to ses the traffic.

I hav a C source, that compiled, works, sending and receiving data.
But as I don't know C :(

B4X:
#include <stdio.h>      /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
#include <arpa/inet.h>  /* for sockaddr_in and inet_addr() */
#include <stdlib.h>     /* for atoi() and exit() */
#include <string.h>     /* for memset() */
#include <unistd.h>     /* for close() */
#include <time.h>       /* for time fuctions */

#define RCVBUFSIZE 500   /* Size of receive buffer */

typedef struct
{
    char OperationType,Service,Amount[8+1],ExtraData[22+1];
    char RFU[100+1];
    char ConfigPath[127+1];
} Request;

//void DieWithError(char *errorMessage);  /* Error handling function */

void DieWithError(char *errorMessage)
{
    perror(errorMessage);
    exit(1);
}

//127.0.0.1
//10000

static int ServerLog (char * str, int size)
{
    FILE *stream;
    time_t dt_tm;
    char aux[100];
    char filename[40];
    struct tm * now;
    memset(filename,0,40);
    //if (logos.state)
    {
        dt_tm=time(NULL);
        now=localtime(&dt_tm);
        sprintf(filename,"logClient%04d%02d%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
        if ( (stream = fopen( filename, "a+" )) != NULL )
        {
            sprintf(aux,"[%04d/%02d/%02d %02d:%02d:%02d]-",now->tm_year+1900,now->tm_mon+1,now->tm_mday, now->tm_hour,now->tm_min,now->tm_sec);
            fwrite( (char *)aux,1, strlen(aux), stream );
            fwrite( (char *)str,1, size, stream );
            fclose( stream );
        }
    }
    return 0;
}
/* log message as hexa and ascii * */
void ServerLogThis(char *str, int len) {
int i, j, x;
char c;
char logbuf[200];

     //if(!logos.dump) return;
     logbuf[0] = 0;

     sprintf(logbuf, "*************** DUMP CONTENTS length(%d) ***************\n", len);
     ServerLog(logbuf, strlen(logbuf));

     for(i= 0; i < len; ) {
         memset(logbuf, 0, sizeof(logbuf));
         // hexa dump
         for(x= i, j= 0; x < len && j < 16; x++, j++) {
             sprintf(logbuf, "%s%02.02x ", logbuf, (unsigned char)str[x]);
         }
         if(j < 16) {
            while(j < 16)  {
               sprintf(logbuf, "%s   ", logbuf); j++;
            }
         }
         // separator
         sprintf(logbuf, "%s ; ", logbuf);
         // ascii dump
         for(x= i, j= 0; x < len && j < 16; x++, j++) {
             c= str[x];
             if(c < 32 || c > 126) c= '.';
             sprintf(logbuf, "%s%c", logbuf, c);
         }
         // Mete NewLine
         sprintf(logbuf, "%s\n", logbuf);
         // print dump
         ServerLog(logbuf, strlen(logbuf));
         i+= j;
     }
     sprintf(logbuf, "---------------------------------------------\n");
     ServerLog(logbuf, strlen(logbuf));
}

int main(int argc, char *argv[])
{
    int sock;                        /* Socket descriptor */
    struct sockaddr_in echoServAddr; /* Echo server address */
    unsigned short echoServPort;     /* Echo server port */
    char servIP[15 + 1];                    /* Server IP address (dotted quad) */
    char *echoString;                /* String to send to echo server */
    char echoBuffer[6000];/* Buffer for echo string */
    unsigned int echoStringLen;      /* Length of string to echo */
    int bytesRcvd, totalBytesRcvd;   /* Bytes read in single recv()
                                        and total bytes read */
    char logbuf[200];
    /* Ingelink Request aux fields */
    int tam = 0;
    int *iRet;
      
    echoString=(char*) malloc(sizeof(Request));
  
    memset(servIP,0,sizeof(servIP));
    memset(echoString,0,sizeof(Request));
    memset(echoBuffer,0,sizeof(echoBuffer));

    if ((argc < 3) || (argc > 4))    /* Test for correct number of arguments */
    {
       fprintf(stderr, "Usage: %s <Server IP> <Echo Word> [<Echo Port>]\n", argv[0]);
       // sprintf(servIP,"127.0.0.1");
       // sprintf(echoString,"4000000000");
       exit(1);
    }
    else{
        sprintf(servIP,"%s",argv[1]);             /* First arg: server IP address (dotted quad) */
        sprintf(echoString, "%s",argv[2]);         /* Second arg: string to echo */
    }
  
    if (argc == 4)
        echoServPort = atoi(argv[3]); /* Use given port, if any */
    else //echoServPort = 7;  /* 7 is the well-known port for the echo service */
        echoServPort = 10001;
    printf("POS2GO - Network TRX\n");
    printf("Client running in port %d...\n", echoServPort);
    sprintf(logbuf, "CLIENT START ----------------------->\n");
    ServerLog(logbuf, strlen(logbuf));
    /* Create a reliable, stream socket using TCP */
    if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
        DieWithError("socket() failed");

    /* Construct the server address structure */
    memset(&echoServAddr, 0, sizeof(echoServAddr));     /* Zero out structure */
    echoServAddr.sin_family      = AF_INET;             /* Internet address family */
    echoServAddr.sin_addr.s_addr = inet_addr(servIP);   /* Server IP address */
    echoServAddr.sin_port        = htons(echoServPort); /* Server port */

    /* Establish the connection to the echo server */
    if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
        DieWithError("connect() failed");

    echoStringLen = 2*sizeof(int) + (5 * 1024);  /* Determine input length */

    tam = sizeof(Request);
    /* Send the string to the server */
    if (send(sock, echoString, tam , 0) != tam)
        DieWithError("send() sent a different number of bytes than expected");
    /*
    if(echoString[0] == '4')
    {
        // Sending Cancelation after x seconds //
        printf("Sending Cancelation after 20 seconds...\n");
        sleep(20);
      
        memset(echoString,0,sizeof(Request));
        sprintf(echoString,"6000000000");
        tam = sizeof(Request);
      
        if (send(sock, echoString, tam , 0) != tam)
            printf("send() cancelation error\n");
        else
            printf("send() cancelation ok\n");

        printf("1st Read\n");
        // Receive the same string back from the server //
        totalBytesRcvd = 0;
        printf("Received: \n");                // Setup to print the echoed string //
        while (totalBytesRcvd < echoStringLen)
        {
        // Receive up to the buffer size (minus 1 to leave space for  a null terminator) bytes from the sender //
            if ((bytesRcvd = recv(sock, echoBuffer + totalBytesRcvd, RCVBUFSIZE - 1, 0)) <= 0)
                DieWithError("recv() failed or connection closed prematurely");
            printf("Receiving %d bytes...\n",bytesRcvd);
            totalBytesRcvd += bytesRcvd;   // Keep tally of total bytes //
            echoBuffer[bytesRcvd] = '\0';  // Terminate the string! //      
        }
        sprintf(logbuf, "Cancelation Response Buffer:\n");
        ServerLog(logbuf, strlen(logbuf));
        ServerLogThis(echoBuffer, totalBytesRcvd);      // Print the echo buffer //
        printf("\n");    // Print a final linefeed //
    }*/
  
    printf("2nd Read\n");
    memset(echoBuffer,0,sizeof(echoBuffer));
    /* Receive the same string back from the server */
    totalBytesRcvd = 0;
    printf("Received: \n");                /* Setup to print the echoed string */
    while (totalBytesRcvd < echoStringLen)
    {
        /* Receive up to the buffer size (minus 1 to leave space for
*            a null terminator) bytes from the sender */
        if ((bytesRcvd = recv(sock, echoBuffer + totalBytesRcvd, RCVBUFSIZE - 1, 0)) <= 0)
            DieWithError("recv() failed or connection closed prematurely");
        printf("Receiving %d bytes...\n",bytesRcvd);
        totalBytesRcvd += bytesRcvd;   /* Keep tally of total bytes */
        echoBuffer[bytesRcvd] = '\0';  /* Terminate the string! */
      
    }
  
    //memcpy(iRet, echoBuffer, sizeof(int));
    //memcpy(tam, echoBuffer + sizeof(int), sizeof(int));

    //printf("\nRet:%d\n", *iRet);      /* Print the Ingelink return */
    //printf("\nSize:%d\n", *tam);      /* Print the ticket size */
    sprintf(logbuf, "Request Response Buffer:\n");
    ServerLog(logbuf, strlen(logbuf));
    ServerLogThis(echoBuffer, totalBytesRcvd);      /* Print the echo buffer */
    printf("\n");    /* Print a final linefeed */
    sprintf(logbuf, "<----------------------- CLIENT END\n");
    ServerLog(logbuf, strlen(logbuf));
  
    close(sock);
    free(echoString);
    exit(0);
}
 
Last edited:
Upvote 0
Top