Details of socket using socket ID - java

This question may sound basic one . Are there any functions in c or Java where I can get the socket details like , port , address , buffer size using only socket identifier ?

Some minimal information available with me is posted below.
I don't know much of Java. But as far as 'C' is concerned, you can use the getsockopt function to get the buffer sizes (send buffer and recv buffer) of the socket.
It appears getsockname helps you in getting the ip & port to which the socket is bound to.

In c in the function accept:
csock = accept(sock, (struct sockaddr*)&csin, &recsize);
sock is the socket server(int)
csock is the socket client (int)
recsize is the size
csin is a struct with client's details
csin.sin_addr is the client's address
csin.sin_port is the client's port
From a socket ID try this:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
f()
{
int s;
struct sockaddr_in sa;
int sa_len;
.
.
.
/* We must put the length in a variable. */
sa_len = sizeof(sa);
/* Ask getsockname to fill in this socket's local */
/* address. */
if (getsockname(s, &sa, &sa_len) == -1) {
perror("getsockname() failed");
return -1;
}
/* Print it. The IP address is often zero beacuase */
/* sockets are seldom bound to a specific local */
/* interface. */
printf("Local IP address is: %s\n", inet_ntoa(sa.sin_add r));
printf("Local port is: %d\n", (int) ntohs(sa.sin_port));
.
.
.
}

Related

Connection between C++ Socket and Java Client

I'm creating a server app in C++ and client app in Java. I want to exchange 32 bit integer between them.
And I've got a trouble, because when I'm trying send something from Java's client, I get a random answer in C++ server (e.g. I've send '0' and one time I've got a one number, another time I've got different number. I've read about Little and Big Endian coding, but I think it is another issue, because sending '0' generate a huge value different from 0.
Java Client:
import java.io.DataOutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class Main {
public static void main(String[] args) throws Exception{
Socket socket = new
Socket(InetAddress.getByName("127.0.0.1"),10000);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeInt(0);
}
}
C++ Server:
#include <netinet/in.h>
#include <string>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <cerrno>
#include <cstring>
#include <iostream>
using namespace std;
int main(){
int port = 10000;
string ip_addr = "127.0.0.1";
int domain = AF_INET;
int type = SOCK_STREAM;
int protocol = 0;
int stopCondition = 0xFFFFFFFF;
int socketHandle;
struct sockaddr_in address;
int clientSocketHandle;
struct sockaddr_in clientAddress;
size_t clientAddressSize;
int buffer;
if((socketHandle=socket(domain,type,protocol))<0)
cout<<strerror(errno);
address.sin_family = domain;
inet_pton(domain,ip_addr.c_str(),&address.sin_addr);
address.sin_port=htons(port);
if((bind(socketHandle,(struct sockaddr *)&address,sizeof(address)))<0)
cout<<strerror(errno);
if (listen(socketHandle, 1) < 0)
cout << strerror(errno);
if ((clientSocketHandle = accept(socketHandle, (struct sockaddr *) &clientAddress, (socklen_t *) &clientAddressSize)) < 0)
cout << strerror(errno);
do {
if (recv(clientSocketHandle, &buffer, sizeof(int), 0) > 0)
cout<<buffer<<endl;
} while (buffer != stopCondition);
if(shutdown(clientSocketHandle,SHUT_RDWR)<0)
cout<<strerror(errno);
if(shutdown(socketHandle,SHUT_RDWR)<0)
cout<<strerror(errno);
return 0;
}
How should I implement my client in Java to work properly with my C++ server?

Google Protocol Buffer (Java to C++)

I am attempting to setup a TCP/IP socket connection between Java and C++, with Java on Windows and C++ on a Raspberry Pi. The message being transmitted is a Google Protocol Buffer message, with a proto set as below:
package package_name;
message Win2Pi{
optional int32 num1= 1;
optional int32 num2= 2;
optional int32 num3= 3;
optional int32 num4= 4;
optional bool logic1= 5;
optional bool logic2= 6;
optional bool logic3= 7;
optional bool logic4= 8;
optional bool logic5= 9;
optional int32 num5= 10;
optional bool logic6= 11;
}
I have the following code for Java (which acts as a client):
/* Java Code to Open Socket, Create Protobuf Message, and Send */
Socket clientSocket = new Socket(hostName, portNumber);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
WinToPi.Builder w2p = WinToPi.newBuilder();
w2p.setNum1(255);
w2p.setNum2(255);
w2p.setNum3(255);
w2p.setNum4(255);
w2p.setLogic1(true);
w2p.setLogic2(true);
w2p.setLogic3(true);
w2p.setLogic4(true);
w2p.setLogic5(false);
w2p.setNum5(7);
w2p.setLogic6(true);
w2p.build().writeTo(clientSocket.getOutputStream());
I have the following code for C++ (which acts as a server):
//Protobuf Setup Variables
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[1024];
struct sockaddr_in serv_addr, cli_addr;
int n;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0){
std::cout << "Error Opening Socket!" << std::endl;
exit(1); //error
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0){
std::cout << "Error on Binding!" << std::endl; ;
exit(1); //error
}
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
std::cout << "ERROR on accept" << std::endl;
exit(1);
}
/* Clear Buffer and Read Message from Client */
bzero(buffer,1024);
n = read(newsockfd,buffer,1023);
std::cout << "n: " << n << std::endl;
if (n < 0){
std::cout << "Error Reading From Socket!" << std::endl;
}
/* Translate Shoreside to Pi Message */
std::string inputStr = std::string(buffer);
package_name::WinToPi w2p;
w2p.ParseFromString(inputStr);
With a static message, I am able to receive the appropriate number of bytes and values. With this, I moved to having values change dynamically on the Java side. However, it appears that on the c++ side, I will receive the correct number of bytes but the values will not have changed for a majority of the variables (only the first few). When I check the packaged and transmitted Google Protocol Buffer message on the Java side, it appears that I am sending the correct values. Is there a better approach for receiving a Google Protocol Buffer message in c++?
Your biggest problem seems to be this:
std::string inputStr = std::string(buffer);
When you construct a string like that - from a const char* - it will look for the first NUL as the terminator. You should instead use...
std::string inputStr = std::string(buffer, n);
...which will ensure the entire chunk of received data is stored into the string.
Another problem:
read on a socket may return whatever's sent over multiple calls, so you should always adopt a convention for working out when to stop reading (e.g. a fixed number of bytes known to client and sender - perhaps from a structure size, or a sentinel character or sequence such as newline or NUL, or a fixed-sized length prefix)
this is a natural consequence of buffering over the stream: say your client app calls write/send thrice while the OS is too busy to actually get any of the data into a network packet: when it does do so it may be able to fit the first and half the second "write" into one packet, then send the rest of the second along with the third in another; if the receiver expects each read to read the start of a multi-byte logical message, they're in for a shock
As for better approaches, for some small casual use I've found boost::asio makes for very concise, clear code and is a pleasure to use... lots of docs, examples, tutorials online.

sending doubles via TCP between Boost ASIO server and Java client

I am trying to set up a simple Boost ASIO server with a single Java client.
I am able to send and successfully receive strings between the two. However, when I try to send double values, only garbage comes out on the other end.
Below is stand alone code that shows my basic setup (with a C++ Boost ASIO server and a Java client). When they are run, they do the following four sequential tasks:
The client sends a string to the server, which is successfully received and printed out.
The server sends a string to the client, which is successfully received and printed out.
The client sends a double value to the server, which is received but does NOT print out
correctly.
The server sends a double value to the client, which is received but does NOT print out
correctly.
Does anyone know what I am doing wrong? I am admittedly very new to networking (and Java). I have been through the Boost ASIO documentation and examples but to know avail.
C++ Boost ASIO server code:
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/array.hpp>
using boost::asio::ip::tcp;
int main()
{
unsigned short const PORT = 19876;
try
{
boost::asio::io_service ioService;
tcp::acceptor acceptor(ioService, tcp::endpoint(tcp::v4(), PORT));
while (true)
{
// Listen for clients
std::cout << "Listening for client..." << std::endl;
tcp::socket socket(ioService);
acceptor.accept(socket);
std::cout << "Client heard..." << std::endl;
size_t len;
// Receive string from client and print it out
boost::array<char, 128> cBuf;
len = socket.read_some(boost::asio::buffer(cBuf, sizeof(cBuf)));
std::cout.write(cBuf.data(), len);
// Send string to client
std::string message = "Server string to send to client\n";
boost::asio::write(socket, boost::asio::buffer(message));
// Receive double from client and print it out
double dVal1 = -1.0;
char * p_dVal1 = reinterpret_cast<char *>(&dVal1);
len = socket.read_some(boost::asio::buffer(p_dVal1, sizeof(double)));
std::cout << dVal1<< std::endl; // prints out garbage
// Send double to client
double dVal2 = 6.28;
char const * p_dVal2 = reinterpret_cast<char const *>(&dVal2);
boost::asio::write(socket, boost::asio::buffer(p_dVal2, sizeof(double)));
}
}
catch (std::exception & e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
Java client code:
import java.io.*;
import java.net.*;
public class Client
{
final static String HOST = "localhost";
final static int PORT = 19876;
public static void main(String[] args) throws IOException
{
Socket socket = new Socket(HOST, PORT);
// Send string to server
PrintWriter pos = new PrintWriter(socket.getOutputStream(), true);
pos.println("Client string to send to server");
// Receive string from server
BufferedReader bis =
new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(bis.readLine());
// Send double value to server
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeDouble(3.14);
// Receive double from server
DataInputStream dis = new DataInputStream(socket.getInputStream());
System.out.println(dis.readDouble()); // prints out garbage
socket.close();
pos.close();
bis.close();
dos.close();
dis.close();
}
}
Thank you very much in advance!!!
Aaron
You need to use a lexical_cast, not a reinterpret_cast.
With reinterpret_cast, you're telling the compiler to literally interpret the double* bit pattern as a const char* bit pattern. Instead, your cast should create a new structure with ascii chars that represent the number in an ascii bit pattern.
Also, you should ensure that you're managing endianess. You should properly convert to and from network endianess on both the client and server. See this answer for additional information.

Java DataInputStream readInt() from C++ Client getting huge value

I suspect this has to do with endianness but I'm not sure how to fix it. I have a C++ client telling a Java server how many bytes it's about to send where the Java server just calls readInt() on the input stream. Then the server goes onto read the rest of the data.
At the moment if the C++ server calls:
char l = '3';
BytesSent = send( Socket, &l, 1, 0 );
Then the corresponding Java side is:
int lBytesSent = m_InDataStream.readInt();
m_AckNack = new byte[lBytesSent];
m_InDataStream.read(m_AckNack)
Bytes lBytesSent tends to be some massive value which then just throws an exception when it comes to creating the array (not surprisingly)
The C++ socket is simply opened up with:
Socket = socket(AF_INET, SOCK_STREAM, 0);
Option = 1000;
setsockopt(Socket, SOL_SOCKET, SO_RCVTIMEO, (char *) &Option, sizeof(Option));
server.sin_family = AF_INET;
server.sin_port = htons(Port);
server.sin_addr.s_addr = INADDR_ANY;
memset(&(server.sin_zero), '\0', 8);
connect(Socket, (sockaddr*)&server, sizeof(server));
And the Java side:
ServerSocket listener = new ServerSocket(port);
Socket server;
server = listener.accept();
Removing the error checking for clarity.
Any suggestions would be great
Many Thanks
Mark
Try running the number through htonl before sending it (on the C++ side):
long x = htonl(42); /* x now contains 42 represented in network byte order */

Socket programming, C-java

Hey guys, i've been searching for some info on sockets programming for a few hours right now and still can't understand how to solve a problem i have.
I've been asked to do the following :
The server receives an UDP datagram at the port 8080, sent from a client, in the datagram the client sends an array of chars that represents a number(9090)
The server will create a new socket, establish a TCP connection with the client at the port
9090.
Through the tcp connection, the server will read the a name, sent by the client.
We're asked to write a client able to do those tasks in C, the server is already done and is found in a .jar file
The program should run like this : ./client SERVER_NAME
and the server: java -jar server.jar
i got as far as this goes...with a think it covers the first part(sending the udp package) but not quite sure how to follow:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define SERVERPORT "8080" // the port users will be connecting to
int main(int argc, char *argv[])
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes;
if (argc != 2) {
fprintf(stderr,"usage: talker hostname\n");
exit(1);
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
if ((rv = getaddrinfo(argv[1], SERVERPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "talker: failed to bind socket\n");
return 2;
}
int num = 9090;
num = htonl(num);
if ((numbytes = sendto(sockfd, num, sizeof(num), 0,
p->ai_addr, p->ai_addrlen)) == -1) {
perror("talker: sendto");
exit(1);
}
Does the java server provide any feedback you can use to verify the your UDP thus far? If so, I would verify and proceed as follows..
Setup a separate socket to make the TCP connection. There are many resources on the Internet showing how to do that (Google 'c tcp client example'). Since UDP is an unreliable best-effort protocol you will want to have a method for retrying the connection. One solution might be to loop, sending the UDP datagram and trying the TCP connection on the other socket until the connection is made (or some other time limit or maximum retry limit is reached).
// setup TCP socket to connect to your chosen port 'num'...
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
// handle error
struct sockaddr_in tcpServAddr;
memset(&tcpServAddr, 0, sizeof(tcpServAddr));
tcpServAddr.sin_family = AF_INET;
tcpServAddr.sin_addr.s_addr = inet_addr(<insert server ip here>);
tcpServAddr.sin_port = htons(num);
const int iMaxTries = 10;
int iTryCount = 0;
bool bConnected = false;
while(!bConnected && (iTryCount < iMaxTries)) {
// using your bock from above:
if ((numbytes = sendto(sockfd, num, sizeof(num), 0,
p->ai_addr, p->ai_addrlen)) == -1) {
perror("talker: sendto"); // may want to output strerr(errno) for more information
break; // something is wrong if we can't send UDP. bail and figure that out
}
++iTryCount;
// try the TCP connection on the target port
if (connect(tcpSockFd, (struct sockaddr *) &tcpServAddr, sizeof(tcpServAddr)) == 0) {
bConnected = true;
} else {
// report error
}
}
if (bConnected) {
// send(...) name on tcpSockFd
}
// cleanup sockets
None of the above is tested, but hopefully it gives you some general direction.

Categories

Resources