I am writing a program for UDP Multithreading server.I have written quote based on the inputs and psuedo codes which i have taken from the Stack overflow.When i execute my program my computer is hanging up.Could anyone please correct the issue with the below code and provide me optimal solution for writing a UDP server which handles Multithreading.
public class MyownServer extends JFrame{
private JTextArea jta = new JTextArea();
public static void main(String[] args) throws Exception {
new MyownServer();
}
public MyownServer(){
add(new JScrollPane(jta), BorderLayout.CENTER);
setVisible(true);
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Server");// It is necessary to show the frame here!
try{
DatagramSocket firstsocket = new DatagramSocket(8100);;
int id = 0;
while (true) {
byte[] buf = new byte[256];
DatagramPacket receivePacket =
new DatagramPacket(buf, buf.length);
ClientServiceThread cliThread = new ClientServiceThread(firstsocket, receivePacket);
cliThread.start();
}
}
catch(IOException ex) {
ex.printStackTrace();
}
}
}
public class ClientServiceThread extends Thread {
private JTextArea jta = new JTextArea();
DatagramPacket packet;;
boolean running = true;
DatagramPacket sendPacket;
DatagramSocket socket;;
byte[] buf;
ClientServiceThread(DatagramSocket socket,DatagramPacket packet) {
this.socket=socket;
this.packet=packet;
}
public void run()
{
try {
// Compute and process
byte[] data = new byte[256];
DatagramPacket response = new DatagramPacket(data, data.length);
socket.receive(packet);
double rate = Double.parseDouble(new String(buf).trim());
sendPacket.setAddress(packet.getAddress());
sendPacket.setPort(packet.getPort());
socket.send(sendPacket);
socket.receive(packet);
double years = Double.parseDouble(new String(buf).trim());
socket.send(sendPacket);
socket.receive(packet);
double loan = Double.parseDouble(new String(buf).trim());
double monthlyPayment = loan * (rate / 1200) / (1 - (Math.pow(1 / (1 + (rate / 1200)), years * 12)));
double totalPayment = monthlyPayment * years * 12;
sendPacket.setData(new Double((double)(monthlyPayment * 100) / 100.00).toString().getBytes());
socket.send(sendPacket);
socket.receive(packet);
sendPacket.setData(new Double((double)(totalPayment * 100) / 100.00).toString().getBytes());
socket.send(sendPacket);
socket.close();
jta.append("Interest Rate is " + rate + '\n');
jta.append("Number Of years " + years + '\n');
jta.append("Loan Amount is " + loan + '\n');
jta.append("Monthly payment " + monthlyPayment + '\n');
jta.append("Total Payment " + totalPayment + '\n');
} catch (Exception e) {
e.printStackTrace();
}
}
}
I appreciate your help.Thanks in advance.
This section just sits there creating thread after thread forever.
while (true) {
byte[] buf = new byte[256];
DatagramPacket receivePacket
= new DatagramPacket(buf, buf.length);
ClientServiceThread cliThread = new ClientServiceThread(firstsocket, receivePacket);
cliThread.start();
}
You should use a ThreadPool.
Your server socket should wait to receive connections from the clients inside a infinite loop. You do have a loop but you are missing a receive function call in there.
The receive call shall return the client socket on which then you can communicate with the client henceforth.
Here's a complete example for working with DatagramSockets
https://docs.oracle.com/javase/tutorial/networking/datagrams/clientServer.html
Related
I'm working on some code to interact with a server and send a file in 1000 byte chunks. I want to use setSoTimeout to resend a packet after 5 seconds if I have not received an ACK from the server by then. I have searched for the answer to this but to no avail. Here are some links i checked out and attempted:
What is the functionality of setSoTimeout and how it works?
how to use socket.setSoTimeout()?
setSotimeout on a datagram socket
I am under the impression that when the timer is going you are continuously waiting for the ACK. Is this the case? I am never receiving an ACK from the server, although I was at one point before.
import java.net.*;
import java.io.*;
import java.util.*;
public class FTPClient {
Socket tcpSocket;
DatagramSocket udpSocket;
DataInputStream dataIn;
DataOutputStream dataOut;
BufferedReader br;
String fileName;
int time;
int portNum;
/**
* Constructor to initialize the program
*
* #param serverName server name
* #param server_port server port
* #param file_name name of file to transfer
* #param timeout Time out value (in milli-seconds).
*/
public FTPClient(String server_name, int server_port, String file_name, int timeout) {
System.out.println("Server Name: " + server_name + " Server Port: " + server_port
+ " File Name: " + file_name + " Timeout: " + timeout);
fileName = file_name;
time = timeout;
portNum = server_port;
try {
Socket tcpSocket = new Socket(server_name, server_port);
dataIn = new DataInputStream(tcpSocket.getInputStream());
dataOut = new DataOutputStream(tcpSocket.getOutputStream());
br = new BufferedReader(new InputStreamReader(System.in));
}
catch (Exception ex) {
System.out.println("Exception in FTPClient initialization: " + ex);
}
}
/**
*Send file content as Segments
*
*/
public void send() {
try {
File f = new File(fileName);
if (!f.exists()) {
System.out.println("File does not exist...");
return;
}
System.out.println("Sending filename (" + fileName + ") to server.");
dataOut.writeUTF(fileName);
byte msgFromServer = dataIn.readByte();
if (msgFromServer == 0) {
System.out.println("Server ready to receive file");
}
// Create a UDP socket to send the file to the server
DatagramSocket udpSocket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName("localhost");
FileInputStream fileIn = new FileInputStream(f);
int seqNum = 0;
int i = 0;
Boolean received = false;;
byte[] chunks = new byte[1000];
int rc = fileIn.read(chunks);
while(rc != -1)
{
System.out.println("Iteration #: " + i);
System.out.println(rc);
// rc should contain the number of bytes read in this operation.
//if (rc < 1000) {
//System.out.println("Bytes read less than 1000");
//System.out.println("Sequence Number: " + seqNum);
//System.out.println("Packet too small to send");
//}
System.out.println("Bytes read greater than 1000");
System.out.println("Sequence Number: " + seqNum);
while (received == false) {
System.out.println("You are looping and sending again");
transferPacket(seqNum, IPAddress, chunks);
received = getResponse();
}
rc = fileIn.read(chunks);
if (seqNum == 1) {
seqNum = 0;
}
else {
seqNum = 1;
}
i++;
}
}
catch (Exception e) {
System.out.println("Error: " + e);
}
}
public Boolean getResponse() {
try {
DatagramSocket udpSocket = new DatagramSocket();
System.out.println("You are in getResponse()");
byte[] receiveData = new byte[1000];
udpSocket.setSoTimeout(time); // set timer
while (true) {
try {
System.out.println("You are receiving a packet");
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
udpSocket.receive(receivePacket);
Segment unwrap = new Segment(receivePacket);
int num = unwrap.getSeqNum();
System.out.println("Received ACK with Sequence Number: " + num);
return true;
}
catch (SocketTimeoutException t) {
System.out.println("Timeout: return false to send()");
return false;
}
}
}
catch (Exception e) {
System.out.println("You don't wanna be here");
return false;
}
}
public void transferPacket(int seqNum, InetAddress IPAddress, byte[] chunks) {
try {
DatagramSocket udpSocket = new DatagramSocket();
byte[] sendData = new byte[1000];
Segment s = new Segment(seqNum, chunks);
sendData = s.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, portNum);
udpSocket.send(sendPacket);
System.out.println("Sent Packet with sequence number " + seqNum);
}
catch (Exception e) {
System.out.println("Exception in transferPacket: " + e);
}
}
/**
* A simple test driver
*
*/
public static void main(String[] args) {
String server = "localhost";
String file_name = "";
int server_port = 8888;
int timeout = 5000; // milli-seconds (this value should not be changed)
// check for command line arguments
if (args.length == 3) {
// either provide 3 parameters
server = args[0];
server_port = Integer.parseInt(args[1]);
file_name = args[2];
}
else {
System.out.println("Wrong number of arguments, try again.");
System.out.println("Usage: java FTPClient server port file");
System.exit(0);
}
FTPClient ftp = new FTPClient(server, server_port, file_name, timeout);
System.out.printf("Sending file \'%s\' to server...\n", file_name);
try {
ftp.send();
}
catch (Exception e) {
System.out.println("Exception: " + e);
}
System.out.println("File transfer completed.");
}
}
You need to keep using the same UDP socket for the life of the application, not a new one per packet, and use it for both sending and receiving.
At present you are also leaking UDP sockets like a firehose.
When im using the google play app to download apps it's usually about 5mb per second.
But when im using my laptop as a server that sends a 100mb byte array,
when i download (read) this array from my smartphone it's about 2.5mb per second.
Server Code, runs on my computer.
class SpeedTestServer {
public static void main(String[] args) throws IOException {
int port = 1234;
ServerSocket server = new ServerSocket(port);
while(true) {
Socket clientConn = server.accept();
BufferedOutputStream out = new BufferedOutputStream(clientConn.getOutputStream());
out.write(new byte[1024 * 1024 * 100]);
out.flush();
clientConn.close();
}
}
}
Cleint Code, runs on my smartphone.
public static void main(String[] args) throws IOException {
int port = 1234;
String host = "my computer internal ip";
Socket client = new Socket(host, port);
BufferedInputStream in = new BufferedInputStream(client.getInputStream());
byte[] buffer = new byte[1024 * 1024 * 100];
int sum = 0;
Date start = new Date();
System.out.println("Starting! " + start.toString());
while((sum += in.read(buffer, sum, buffer.length - sum)) != -1) {
if (sum == 1024 * 1024 * 100) {
Date end = new Date();
System.out.println("Finished! " + end.toString() + " " + sum);
break;
}
}
}
Note: I'm currently learning UDP and how effective a VoIP system would be in comparison with a TCP system, I've already done TCP so please no one comment TCP is better etc..
So I'm trying to add a sequence number to the packets so I can order them on the server end and prepare for any lost packets, by repeating the previous for example
Problem: I read a stackoverflow that said using DataOutputStreams is a good way to go about this, so I implemented it. however when using the code dos.writeInt(sequenceNumber++); I get a horrible repetitive crackle. I was thinking maybe the problem is the amount of bytes that im sending.
Thank you in advance, any pointers will be great
boolean running = true;
try {
AudioRecorder recorder = new AudioRecorder();
int sequenceNumber = 0;
while (running) {
byte[] tempBuffer = recorder.getBlock();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.write(tempBuffer);
dos.writeInt(sequenceNumber++);
dos.flush();
DatagramPacket sendPacket = new DatagramPacket(baos.toByteArray(), baos.size(), clientIP, PORT);
sending_socket.send(sendPacket);
}
recorder.close();
} catch (Exception e) {
System.out.println("Error" + e);
Server end:
byte[] buffer = new byte[512];
byte[] temp = new byte[512];
try {
// CODE TO RECEIVE THE AUDIO
AudioPlayer player = new AudioPlayer();
int expectedValue = 0;
while (running) {
//Vector used to store audio blocks (32ms/512bytes each)
Vector<byte[]> voiceVector = new Vector<>();
// creates a new udp packet to receive the audio
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
receiving_socket.receive(packet);
// creates a byte array from the data
byte[] udpPacketBytes = packet.getData();
ByteArrayInputStream baos = new ByteArrayInputStream(udpPacketBytes);
DataInputStream dos = new DataInputStream(baos);
int receivedValue = dos.readInt();
if (receivedValue == expectedValue) {
byte[] filteredByteArray = Arrays.copyOfRange(udpPacketBytes, 4, udpPacketBytes.length - 4);
voiceVector.add(filteredByteArray);
Iterator<byte[]> voiceItr = voiceVector.iterator();
while (voiceItr.hasNext()) {
player.playBlock(voiceItr.next());
}
} else {
// play the previous again
byte[] filteredByteArray = Arrays.copyOfRange(temp, 4, temp.length - 4);
voiceVector.add(filteredByteArray);
Iterator<byte[]> voiceItr = voiceVector.iterator();
while (voiceItr.hasNext()) {
player.playBlock(voiceItr.next());
}
// play the current one
byte[] fba = Arrays.copyOfRange(udpPacketBytes, 4, udpPacketBytes.length - 4);
voiceVector.add(fba);
Iterator<byte[]> vItr = voiceVector.iterator();
while (vItr.hasNext()) {
player.playBlock(vItr.next());
}
}
System.out.println(receivedValue + " " + expectedValue);
expectedValue = receivedValue + 1;
temp = packet.getData();
}
} catch (Exception e) {
System.out.println("yo");
}
//Close the socket
receiving_socket.close();
You are writing the sequence number but you are not reading or removing it so your sequence number ends up in the audio.
I suggest you read the same format you write.
I made a UDP server client architecture with multi-thread the problem is when I send from the server to the client another client thread get the packet and so for all .. how can I specify the thread in which UDP should send back the packet ??
Client
public UDPClient(int port) throws SocketException
{
this.socket = new DatagramSocket();
this.arg1 = (int) (Math.random() * 1000) ;
this.arg2 = (int) (Math.random() * 1000) ;
this.port = port ;
}
public void run()
{
try{
String x = arg1 + " + " + arg2;
BUFFER = x.getBytes();
InetAddress ip = InetAddress.getByName("127.0.0.1");
packet = new DatagramPacket(BUFFER , BUFFER.length,ip,port);
printOutput(new String("Client send" + x));
socket.send(packet);
socket.receive(packet);
String output = new String(packet.getData(),0,packet.getLength());
printOutput(new String("receive " + x + "=" + output));
}
catch(IOException e)
{
System.out.println("UDP sending problem " + e.getMessage());
}
}
Server
public void run()
{
while(true)
{
try{
packet = new DatagramPacket(BUFFER,BUFFER.length);
socket.receive(packet);
executor.execute(new UDPServerCore(socket,packet,BUFFER));
}
catch(IOException e)
{
System.out.println("UDP receiving packet problem "
+ e.getMessage());
}
}
}
ServerCore
#Override
public void run(){
String x = new String(packet.getData(),0,packet.getLength());
String y = parseString(x);
BUFFER = y.getBytes();
//packet.setData(y.getBytes());
DatagramPacket res = new DatagramPacket(BUFFER , BUFFER.length
,packet.getAddress(),packet.getPort());
try{
socket.send(res);
}
catch(IOException e)
{
System.out.println("Something went wrong " + e.getMessage());
}
}
synchronized private static String parseString(String x )
{
String arr[] = x.split(" ");
int z = Integer.parseInt(arr[0]);
int y = Integer.parseInt(arr[2]);
y = y + z;
writeServer.append(x+ "=" + y +"\n");
return String.valueOf(y);
}
I solved it as the problem was when i created the port of the thread i should have create all the client threads with specified port first then starting each thread.
Y̶o̶u̶ ̶c̶o̶u̶l̶d̶ ̶t̶r̶y̶ ̶t̶o̶ ̶a̶s̶s̶i̶g̶n̶ ̶a̶n̶ ̶I̶D̶ ̶t̶o̶ ̶t̶h̶e̶ ̶p̶a̶c̶k̶e̶t̶ ̶t̶o̶ ̶t̶r̶a̶c̶k̶ ̶t̶h̶e̶ ̶c̶u̶r̶r̶e̶n̶t̶ ̶s̶e̶s̶s̶i̶o̶n̶ ̶i̶t̶ ̶ b̶e̶l̶o̶n̶g̶s̶ ̶t̶o. UDP as opposed to TCP is a no confirmation and no connection protocol. UDP does not support "streams" of data so you have to find a way to dispatch each packet to the corresponding "session handler".
If you could explain more what you're trying to accomplish I think anyone here could help you more.
edit:
Each udp packet contains source address and port. You can use those to recognize and store data for every client that connects. Hint: you could use a map / dictionary and when receiving a packet retrieve your session object using client address and port as key
I am trying to set up a program that looks into UDP performance of packets and response times on my network. I have a client and server side class, for which I am specifying the packet size which to send pieces of text. For example, if I want to send a word of "Tester" in a 4 byte packet, it will send the "TEST" part but not reiterate through the rest of the word. I have tried to add in a while loop, but i don't think what I have is correct as it continuously sends the first 4 bytes. Does anyone know what sort of loop I need and where abouts it should be placed to get the outcome I am after? Code for the client is below. Many thanks in advance for any guidance.
//UDP Client
//Usage: java UDPClient [server addr] [server port]
import java.io.*;
import java.net.*;
public class UDPClient extends variable {
// static Integer portNo = 4444;
static Integer byteSize = 4;
public static void main(String[] args) throws Exception {
SocketForm form = new SocketForm();
long startTime; // Starting time of program, in milliseconds.
long endTime; // Time when computations are done, in milliseconds.
double time;
//get server address
String serverName = "localhost";
if (args.length >= 1)
serverName = args[0];
InetAddress serverIPAddress = InetAddress.getByName(serverName);
//get server port;
int serverPort = form.cliportNo;
if (args.length >= 2)
serverPort = Integer.parseInt(args[1]);
//create socket
DatagramSocket clientSocket = new DatagramSocket();
//get input from keybaord
byte[] sendData = new byte[byteSize];
BufferedReader inFromUser = new BufferedReader(new InputStreamReader (System.in));
while (true){ //incorrect as it is only repeating the first four bytes of the word typed in the console
String sentence = inFromUser.readLine();
startTime = System.currentTimeMillis();
sendData = sentence.getBytes();
//construct and send datagram;
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, serverIPAddress, serverPort);
clientSocket.send(sendPacket);
//receive datagram
byte[] receiveData = new byte [byteSize];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
//print output
String sentenceFromServer = new String(receivePacket.getData());
System.out.println("From Server:" + sentenceFromServer);
//close client socket
//clientSocket.close();
endTime = System.currentTimeMillis();
time = endTime - startTime;
//System.out.println("Time :" + time);
}
} //end of main
} //end of UDPClient
Do you mean like this?
private void sendChunked( String msg, int chunkSizeInBytes ) {
byte[] msgBytes = msg.getBytes();
for( int index = 0; index < msgBytes.length ; index += chunkSizeInBytes ) {
DatagramPacket packet = new DatagramPacket( msgBytes, index, Math.min( chunkSizeInBytes, msgBytes.length-index ));
send( packet ); // You know how that works ...
}
}