In cx_Oracle, I obtained a Connection object using tnsnames.ora
Example:
conn = cx_Oracle.connect ('scott', 'tiger', 'DBNAME')
I'm trying to get an IP from a connection object (= conn), but I can not figure out how to do it.
It is practically impossible. Even OCI does not support it. There was a trick in OCI to convert OCI Connection struct into the old Oracle7 connection context, and this structure contains "file handle" number for TCP socket to the database. From this file/socket descriptor you could get IP.
If you use tnsnames.ora you can easily parse it. But in case of Oracle RAC you 1st connect SCAN lister, this one will send you just redirect packet to some cluster node. TCP connection to scan listener is closed and a new TCP connection is opened, based on information received from SCAN listener.
Related
I'm currently working on a ABAP Push Channel server to WebSocket client connection and I need the IP-address of the client in order to identify whether this client is the one I want to send the message to. In my scenario there could be multiple WebSocket connections.
Now there is the ssi_websocket_table table and the ssi_websocket_table_row row with the the field caller_ip, however this gives me the IP address of the DNS-Server of the network I'm connected to, and I expected the IP address of my local PC since the WebSocket-client is running on this machine.
Is there any other way to get the clients IP address from an active WebSocket connection in ABAP?
P.S. Looking at all the table entries, it shows the correct IP when using a different server configuration, as soon as I know why that's the case I will report back.
As pointed out by vwegert it makes no sense to use the IP to tell the WebSockets apart, I think it would probably be better to use an ID for each WebSocket connection instead.
You could get the IP from the WebSocket server context which gets the IP header apparently from the opening HTTP handshake for the connection:
DATA(lo_context) = i_context. " IF_APC_WSP_SERVER_CONTEXT type
DATA(lo_request) = lo_context->get_initial_request( ).
" initialize G_CONTEXT_ID_FIELD for PCP_SET_CONTEXT_FIELDS
DATA(lv_id) = lo_request->get_header_field( if_http_header_fields_sap=>remote_addr ).
the sample is taken from the SAP standard class CL_APC_WS_EXT_ABAP_ONLINE_COMM, ON_MESSAGE method.
Apologies for a newbie question, but that's me - new to Oracle.
My client and oracle server are separated by a firewall. A limited set of IP addresses can be routed through this firewall. One routable IP is the address of a SCAN listener, which redirects to oracle servers that have non-routable IPs.
I am able to connect SQL Developer to my database, but not a simple ODP.Net client.
Using wireshark, I see that when SQL Developer connects to the SCAN listener, SCAN replies with a redirect to a random port on the SCAN IP, which it presumably then proxies to the actual Oracle server. Wireshark reveals that when ODP.Net tries to connect, SCAN replies with a redirect to the actual IP of the back-end server, which IP is not routable.
I'm looking for advice on how to get ODP.Net to enjoy the behavior that SCAN is offering SQL Developer.
I attempted to use the same connection string, completely bypassing tnsnames.ora for simplicity. In SQL Developer, I configured a connection using just IP address, port and service name. I then used wireshark to observe the connection string that SQL Developer sent to the server (yes, SQL Dev repeats the CID section):
(DESCRIPTION=
(ADDRESS=(PROTOCOL=TCP)(HOST=10.130.X.Y)(PORT=1521))
(CONNECT_DATA=
(CID=(PROGRAM=SQL Developer)(HOST=__jdbc__)(USER=myusername))
(SERVICE_NAME=myservice)
(CID=(PROGRAM=SQL Developer)(HOST=__jdbc__)(USER=myusername))))
I plugged this same connection string into an OracleConnection
var bldr = new Oracle.DataAccess.Client.OracleConnectionStringBuilder();
bldr.DataSource = #"(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=10.130.X.Y)(PORT=1521))(CONNECT_DATA=(CID=(PROGRAM=SQL Developer)(HOST=__jdbc__)(USER=myusername))(SERVICE_NAME=myservice)(CID=(PROGRAM=SQL Developer)(HOST=__jdbc__)(USER=myuser))))";
var connection = new Oracle.DataAccess.Client.OracleConnection(bldr.ConnectionString);
connection.Open();
connection.Close();
And instead of connecting I receive a timeout. Further examination of captured packets reveals the behavior detailed above: SCAN acts as a proxy for SQL Developer but not for ODP.
I'm trying to implement TCP hole punching with windows socket using mingw toolchain. I think the process is right but the hole doesn't seems to take. I used this as reference.
A and B connect to the server S
S sends to A, B's router IP + the port it used to connect to S
S does the same for B
A start 2 threads:
One thread tries connecting to B's router with the info sent by S
The other thread is waiting for an incoming connection on the same port used to connect to its router when it connected to S
B does the same
I have no issue in the code I think since:
A and B does get each other ip and port to use
They are both listening on the port they used to connect to their router when they contacted the server
They are both connecting to the right ip and port but get timed out (code error 10060)
I am missing something ?
EDIT: With the help of process explorer, I see that one of the client managed to establish a connection to the peer. But the peer doesn't seems to consider the connection to be made.
Here is what I captured with Wireshark. For the sake of the example, the server S and the client A are on the same PC. The server S listens on a specific port (8060) redirected to that PC. B still tries to connect on the right IP because it sees that the public address of A sent by S is localhost and therefore uses the public IP of S instead. (I have replaced the public IPs by placeholders)
EDIT 2: I think the confusion is due to the fact that both incoming and outcoming connection request data are transfered on the same port. Which seems to mess up the connection state because we don't know which socket will get the data from the port. If I quote msdn:
The SO_REUSEADDR socket option allows a socket to forcibly bind to a
port in use by another socket. The second socket calls setsockopt with
the optname parameter set to SO_REUSEADDR and the optval parameter set
to a boolean value of TRUE before calling bind on the same port as the
original socket. Once the second socket has successfully bound, the
behavior for all sockets bound to that port is indeterminate.
But talking on the same port is required by the TCP Hole Punching technique to open up the holes !
A start 2 threads:
One thread tries connecting to B's router with the info sent by S
The other thread is waiting for an incoming connection on the same port used to connect to its router when it connected to S
You can't do this with two threads, since it's just one operation. Every TCP connection that is making an outbound connection is also waiting for an incoming connection. You simply call 'connect', and you are both sending outbound SYNs to make a connection and waiting for inbound SYNs to make a connection.
You may, however, need to close your connection to the server. Your platform likely doesn't permit you to make a TCP connection from a port when you already have an established connection from that same port. So just as you start TCP hole punching, close the connection to the server. Bind a new TCP socket to that same port, and call connect.
A simple solution to traverse into NAT routers is to make your traffic follow a protocol that your NAT already has an algorithm for forwarding, such as FTP.
Use Wireshark to check tcp connection request(3-way Handhsake process) is going properly.
Ensure your Listener thread is having select() to de-multiplex the descriptor.
sockPeerConect(socket used to connect Other peer) is FD_SET() in Listener Thread.
Ensure your are checking
int Listener Thread()
{
while(true)
{
FD_SET(sockPeerConn);
FD_SET(sockServerConn);
FD_SET(nConnectedSock );
if (FD_ISSET(sockPeerConect)
{
/// and calling accept() in side the
nConnectedSock = accept( ....);
}
if (FD_ISSET(sockServerConn)
{
/// receive data from Server
recv(sockServerConn );
}
if (FD_ISSET(nConnectedSock )
{
/// Receive data from Other Peer
recv(nConnectedSock );
}
}
}
5.Ensure you are simultaneously starting peer connection A to B and B to A.
6.Start your Listener Thread Prior to Connection to server and Peer and have Single Listener Thread for receiving Server and Client.
not every router supports tcp hole punching, please check out the following paper which explains in detail:
Peer-to-Peer Communication Across Network Address Translators
java.sql.SQLException: Io exception: The Network Adapter could not establish the
connection at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java)
I am getting this error when data in database is increased (nearly 3000). It works fine with limited data (say 100).
The Network Adapter could not establish the connection
Is typically thrown when
the Oracle listener is not running
the wrong hostname was specified in the connection url
the wrong port was specified in the connection url
the port is blocked by firewall
I have never seen it related to "increasing" the data in the database
In order to receive datagrams through an UDP connection I have created an object of type UDPClient.
receivedNotificationSock = new UdpClient();
However once done and on using the receive method:
receivedHostNameBuffer=receivedNotificationSock.Receive(ref receivedNotificationIP);
I am getting an exception saying that I must call the bind method.
But there is no bind method in the UDPClient class.
Could You guys please provide me with the code if possible as to what should be done to overcome this exception.
You need I think to know some more about sockets.
All sockets possess a port number. First, you create a socket - which is almost useless on its own. It just floats there. But then you bind it - you assign it a port number. Now it's useful - now you can send and receive data on it.
Remember, all UDP communications are defined by the quad data set of the IP and port of the source and the IP and port of the destination. A freshly created socket doesn't have an IP address or port; binding gives it an IP address and port.
Unfortunately, I'm not a C# programmer, so I can't properly answer your question. But at least you know why it's important.
Pass the port number into the constructor of your UDP client.
receivedNotificationSock = new UdpClient(21000);
You may need to change firewall settings to allow the bind, though a popup window normally opens when you first run this on your dev machine.
For Socket proramming you need to know the sequence of syscalls you need to do on client side and on the server side.
If you are writting a client :
you open a socket with a socket call.
you then connect to the server port with a connect call
once connect is successful
then you send the request to the server using either a send or sendto or a write
which results in reception of data that you can read using a receive or read
On Server Side
you create a socket
bind it to a port
start listening on the socket for incoming connections from various clients using a listen.
There is a non blocking way of listening for connections as well with a select syscall.
Once the you establish a connection you can essentially read the request and start processing it.
Here's an example in C# that may be useful to you.
http://www.developerfusion.com/article/3918/socket-programming-in-c-part-1/