I've just begun socket programming, and I'm working on an Echo server in Java. One of the things I'd like to do is implement the server in both TCP and UDP and allow the client to choose which protocol to use at runtime.
This is a noob question, but how do I allow a user this option to choose TCP or UDP protocols? I tried putting in an if-else at the beginning which branched on the protocol choice from scanner input, but that just skips the both blocks irrespective of the choice?
Thanks.
I've implemented the TCP echo server:
public class EchoServer
{
public static void main(String[] args) throws IOException
{
ServerSocket serverSocket = null;
try{
serverSocket = new ServerSocket(10007);
}
catch (IOException e)
{
System.err.println("Could not listen on port: 10007.");
System.exit(1);
}
Socket clientSocket = null;
System.out.println ("Waiting for connection.....");
try {
clientSocket = serverSocket.accept();
}
catch (IOException e)
{
System.err.println("Accept failed.");
System.exit(1);
}
System.out.println ("Connection successful");
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),
true);
BufferedReader in = new BufferedReader(
new InputStreamReader( clientSocket.getInputStream()));
String cAddress = "";
String inputLine;
cAddress = clientSocket.getInetAddress().toString();
while ((inputLine = in.readLine()) != null)
{
System.out.println ("Server: " + inputLine + " " + cAddress + " ");
out.println(inputLine + " " + cAddress);
if (inputLine.equals("bye"))
break;
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
}
}
And the client side:
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class EchoClient {
public static void main(String[] args) throws IOException {
Scanner s = new Scanner(System.in);
String serverHostname;
System.out.println("Enter an IP value: ");
serverHostname = s.next();
//String serverHostname = new String ("127.0.0.1");
if (args.length > 0)
serverHostname = args[0];
System.out.println ("Attemping to connect to host " +
serverHostname + " on port 10007.");
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
echoSocket = new Socket(serverHostname, 10007);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + serverHostname);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for "
+ "the connection to: " + serverHostname);
System.exit(1);
}
BufferedReader stdIn = new BufferedReader(
new InputStreamReader(System.in));
String userInput;
System.out.print ("input: ");
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println("echo: " + in.readLine());
System.out.print ("input: ");
}
out.close();
in.close();
stdIn.close();
echoSocket.close();
}
}
There is no way (that I know of) to do conditionals in Java without using the If statement. If your else-if wasn't working, then you were checking the condition wrong. To compare strings in java you use String.equals( String ), you can't use ==.
Try using it again on standard input, but just do something simple.
Like:
Scanner scan = new Scanner( System.in );
System.out.println( "use tcp?" );
String in = scan.nextLine();
if( in.indexOf( "y" ) >= 0 || in.indexOf( "Y" ) >= 0 ){
System.out.println("using tcp");
}else{
System.out.println("not using tcp, use udp instead?");
}
If you want to know how it is possible in the socket level, you should be able to bind your TCP serversocket and UDP serversocket in to the same port. You will have to have separate threads handling each of the sockets. For instructions how to write UDP server socket (called DatagramSocket check this tutorial.
You need to open two separate sockets with different ports in your application.
In addition to that, you need separate Threads in Java, which usage is described in a lot of how to's and tutorials.
For Socket creation use DatagramSocket for UDP and ServerSocket for TCP. I don't know, what you want to do, but you have to know that you have to handle dataloss in UDP for yourself. UDP is common used in streaming audio or video, where it is uncritical, to loss some data.
Validate your application needs. For further information see http://en.wikipedia.org/wiki/User_Datagram_Protocol#Comparison_of_UDP_and_TCP.
Your welcome.
Related
I have connection to TCP server (ip,port) to which meter is connected. I'd like to read the specified data from this port because when I'm using standard read method it sends me the whole data stream which takes about 15 minutes to read. So my question: is there any method I can use to get one specified register's value using his OBIS code (1.1.1.8.0.255 - active energy taken) in java via TCP server?
import java.net.*;
import java.io.*;
public class scratch {
public static void main(String[] args) {
String hostname = "ip (hidden)";
int port = port (hidden);
try (Socket socket = new Socket(hostname, port)) {
OutputStream out = socket.getOutputStream();
InputStream input = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(input);
int character;
StringBuilder data = new StringBuilder();
String test = "/?!\r\n";
byte[] req = test.getBytes();
out.write(req);
while ((character = reader.read()) != '\n') {
data.append((char) character);
}
System.out.println(data);
} catch (UnknownHostException ex) {
System.out.println("Server not found: " + ex.getMessage());
} catch (IOException ex) {
System.out.println("I/O error: " + ex.getMessage());
}
}
}
The message "test" send initiation request to meter and his respond is correct but I dont' know how to put flags (ACK STX ETX) in my request, I've tried something like this:
String test2 = (char)0x6 + "051\r\n";
byte[] req2 = test2.getBytes("ASCII");
out.write(req2);
But meter doesn't recognize it.
A Client socket Program (in windows VM) generates integer from 1 to 10 as per below code
public class ClientSocket {
public static void main(String[] args)
{
try{
InetAddress inetAddress = InetAddress.getLocalHost();
String clientIP = inetAddress.getHostAddress();
System.out.println("Client IP address " + clientIP);
Integer dataSendingPort ;
dataSendingPort = 6999 ;
Socket socket = new Socket("192.168.0.32",dataSendingPort);
String WelcomeMessage = " hello server from " + clientIP ;
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
if(socket.isConnected()){
System.out.println("connection was successful");
}
else{
System.out.println("Error- connection was not successful");
}
for (int x= 0 ; x< 10 ; x++){
bufferedWriter.write(x);
bufferedWriter.flush();
}
bufferedWriter.close();
}
catch (IOException e){
System.out.println(e);
}// catch
finally{
System.out.println("closing connection");
}
} // main
} // class
My server socket program is running on Mac OS as Host Machine, whose code is shown below
public class MyServer {
public static void main(String[] args) throws Exception {
try {
// get input data by connecting to the socket
InetAddress inetAddress = InetAddress.getLocalHost();
String ServerIP = inetAddress.getHostAddress();
System.out.println("\n server IP address = " + ServerIP);
Integer ListeningPort ;
ListeningPort = 6999 ;
ServerSocket serverSocket = new ServerSocket(ListeningPort);
System.out.println("server is receiving data on port # "+ ListeningPort +"\n");
// waiting for connection form client
Socket socket = serverSocket.accept();
if(socket.isConnected()){
System.out.println("Connection was successful");
}
else {
System.out.println("connection was not successful");
}
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Integer s = 0 ;
while (( s = input.read()) >= 0){
System.out.println(input.read());
}
} //try
catch (IOException e)
{
System.out.println(e);
} // catch
} //main
} //socket class
The issue is that output I am receiving is -1 when I use while loop and receive first value i.e 0 without using a loop.
However, I was able to send a single value from client to server, but
how can I send Stream of Values from the client and print it on Server
Side.
Suggestions are most welcome
-1 means end of stream.
Closing the input or output stream of a stock closes the socket.
socket.isConnected() cannot possibly be false at the point you are testing it.
input.ready() isn't a test for end of stream, or end of message, or end of transmission, or anything useful at all really.
Don't flush inside loops.
I'm testing around with client-server communication.
I have a server that should receive messages and print them, and send messages that it gets from System.in using a Socket. The client reads messages from the Socket, and sends back some messages. But for some reason both the server and the client get locked when checking if there is a message from the other end (at readLine()).
This client:
public void run() {
try {
Log.i("DataManager", "Trying to connect to server");
socket.connect(new InetSocketAddress(ADDRESS, PORT), 3000);
Log.i("DataManager", "Connected to: " + socket.getInetAddress());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true); //autoflush
String inputLine;
while (socket.isConnected()) {
if ((inputLine = in.readLine()).isEmpty()){
Log.i("DataManager", "Server says: " + inputLine);
}
synchronized (outcoming){
if (!outcoming.isEmpty()){
for (int i = 0; i < outcoming.size(); i++){
out.println(outcoming.get(i));
outcoming.remove(i);
}
}
}
}
}
...
}//
The Server:
ServerSocket listener = new ServerSocket(PORT);
try {
Socket socket;
socket = listener.accept(); //waits for connection
System.out.println("Client connected: " + socket.getInetAddress());
BufferedReader sysRead = new BufferedReader(new InputStreamReader(System.in));
BufferedReader clientIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true); //autoflush
String inputLine;
out.println("Hello, you are connected to server" + listener.getInetAddress());
while (true){
if ((inputLine = clientIn.readLine()).isEmpty()){
System.out.println("Client says: " + inputLine);
}
String line = sysRead.readLine();
if (line.equals("stop")){
break;
} else {
out.println(line);
}
}
socket.close();
}
I tried solving this by encasing the readLine statements with if(in.ready()) but it didn't help at all. I've been looking around on google and found that this is caused by the fact that readLine() looks for eof, and the stream from the socket only ends when the socket is disconnected. I have no idea how to get around this problem other that writing some kind of protocol where i end my messages with a specific sequence. Is there a better way around this problem?
I wrote a simple socket tutorial about sending/receive messages between client and server. I used DataOutputStream to write the string in stream but server couldn't read it if I used BufferedReader
If I use PrintWriter to write(client side), it works.
What's wrong here? Tks so much.
1. Client:
client = new Socket("localhost", 1982);
DataOutputStream opStr = new DataOutputStream(client.getOutputStream());
//pw = new PrintWriter(client.getOutputStream(), true);
//pw.println("Hello, is there anybody out there?");// Can be read by BufferedReader
opStr.writeUTF("Hello, anyone there?");
opStr.flush();// BufferedReader can't read it
2. Server:
openServer();// port 1982
while(true) {
Socket clientSocket = null;
// listen to connection.
clientSocket = echoServer.accept();
DataInputStream inStr = new DataInputStream(
clientSocket.getInputStream());
//System.out.println("M1: Got msg " + inStr.readUTF());// It showed the content
BufferedReader bfReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
System.out.println("got Messages: ");
String strLine = "";
// Don't show anything
while ((strLine = bfReader.readLine()) != null) {
System.out.println(strLine);
}
}
You can't. If you use writeUTF() at one end, you have to use readUTF() at the other end.
You just have to decide which API you're going to use, instead of trying to mix and match them.
You want to read the files as either text e.g. BufferedReader OR binary e.g. DataInputStream. So you can't use both.
Server.java
public class Server
{
public static void main(String[] args)
{
DataInputStream inStr = null;
String str;
openServer();// port 1982
while(true)
{
Socket clientSocket = null;
// listen to connection.
clientSocket = echoServer.accept();
try
{
inStr = new DataInputStream(clientSocket.getInputStream());
str = inStr.readUTF();
System.out.print((String) str);
System.out.flush();
}
catch (IOException io)
{
System.err.println("I/O error occurred: " + io);
}
catch (Throwable anything)
{
System.err.println("Exception caught !: " + anything);
}
finally
{
if (inStr != null)
{
try
{
inStr.close();
}
catch (IOException io)
{
System.err.println("I/O error occurred: " + io);
}
}
}
}
}
}
I have 2 classes (Client and Server) used to implement simple communication in my application. My code is shown below:
Server:
public class Server {
public static void main(String[] ar) {
int port = 1025; // just a random port. make sure you enter something between 1025 and 65535.
try {
ServerSocket ss = new ServerSocket(port); // create a server socket and bind it to the above port number.
System.out.println("Waiting for a client...");
Socket socket = ss.accept();
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();
DataInputStream in = new DataInputStream(sin);
DataOutputStream out = new DataOutputStream(sout);
BufferedReader keyboard = new BufferedReader(new InputStreamReader(
System.in));
System.out.println("enter meter id ");
String line = null;
while (true) {
line = in.readUTF(); // wait for the client to send a line of text.
System.out.println("client send me this id number " + line);
line = keyboard.readLine();
out.writeUTF(line);
out.flush();
//line = in.readUTF();
System.out.println("Waiting for the next line...");
System.out.println();
}
} catch (Exception x) {
x.printStackTrace();
}
}
}
Client:
public class Client {
public static void main(String[] ar) {
int serverPort = 1025;
String address = "localhost";
try {
InetAddress ipAddress = InetAddress.getByName(address); // create an object that represents the above IP address.
System.out.println(" IP address " + address + " and port "
+ serverPort);
Socket socket = new Socket(ipAddress, serverPort); // create a socket with the server's IP address and server's port.
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();
DataInputStream in = new DataInputStream(sin);
DataOutputStream out = new DataOutputStream(sout);
// Create a stream to read from the keyboard.
BufferedReader keyboard = new BufferedReader(new InputStreamReader(
System.in));
String line = null;
System.out.println("ClientConnected.");
System.out.println("enter meter id");
while (true) {
line = keyboard.readLine(); // wait for the user to type in something and press enter.
System.out.println("Sending this number to the server...");
out.writeUTF(line); // send the above line to the server.
out.flush(); // flush the stream to ensure that the data reaches the other end.
line = in.readUTF(); // wait for the server to send a line of text.
System.out
.println("The server was very polite. It sent me this : "
+ line);
System.out.println();
}
}
catch (Exception x) {
x.printStackTrace();
}
}
}
My problem is that while testing the program I do get communication between the client and server, but while debugging, with a break point on the out.flush line in Server.java, it does not go to the intended destination. This intended destination being the line line = in.readUTF(); of Client.java. Can anyone help me to solve this?
It is good practice to open the OutputStreams before the InputStreams, on your sockets, as said in this question.
This question also clarifies that.
What I suspect here is your client and server are running in two different JVM processes and java debugger cannot debug two JVM at the same time.