spring amqp setConfirmCallback problems - rabbitmq

I configure the rabbitTemplate like below:
#Autowired
public Sender(RabbitTemplate rabbitTemplate) {
//消息是否到达交换机的回调
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (!ack) {
log.info("sender not send message to the right exchange" + " correlationData=" + correlationData + " ack=" + ack + " cause" + cause);
} else {
log.info("sender send message to the right exchange" + " correlationData=" + correlationData + " ack=" + ack + " cause" + cause);
}
});
//消息是否到达正确的消息队列,如果没有会把消息返回
rabbitTemplate.setReturnCallback((message, replyCode, replyText, tmpExchange, tmpRoutingKey) -> {
log.info("Sender send message failed: " + message + " " + replyCode + " " + replyText + " " + tmpExchange + " " + tmpRoutingKey);
//try to resend msg
});
RetryTemplate retryTemplate = new RetryTemplate();
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(500);
backOffPolicy.setMultiplier(10.0);
backOffPolicy.setMaxInterval(10000);
retryTemplate.setBackOffPolicy(backOffPolicy);
rabbitTemplate.setRetryTemplate(retryTemplate);
rabbitTemplate.setMandatory(true);
this.rabbitTemplate = rabbitTemplate;
}
and the send method
public void send() {
System.out.println("sender is sending message");
String uuid1 = UUID.randomUUID().toString();
String uuid2 = UUID.randomUUID().toString();
String uuid3 = UUID.randomUUID().toString();
System.out.println("UUID="+uuid1+"---"+uuid2+"---"+uuid3);
// the right excharge name and routing key
rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME, "aaa.orange.bbb", "hello,world1 2", new CorrelationData(uuid1));
// wrong exchage name
rabbitTemplate.convertAndSend("测试交换机名", "aaa.orange.ccc", "测试错误的交换机名", new CorrelationData(uuid2));
// wrong excharge name
rabbitTemplate.convertAndSend("测试交换机名", "1111111", "测试错误的队列名", new CorrelationData(uuid3));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
my question is when i only code
rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME, "aaa.orange.bbb", "hello,world1 2", new CorrelationData(uuid1));
comment two lines
rabbitTemplate.convertAndSend("测试交换机名", "aaa.orange.ccc", "测试错误的交换机名", new CorrelationData(uuid2));
// wrong excharge name
rabbitTemplate.convertAndSend("测试交换机名", "1111111", "测试错误的队列名", new CorrelationData(uuid3));
the confirmCallback log is "sender send message to the right exchange"
But if I send three message at once, the confirmCallback logs are
three "sender not send message to the right exchange" log and I check the queue, the right message is sending to the queue, how can I fix this problem?

Your question is not clear; if you mean you are sending to a non-existent exchange - that is considered fatal for the channel so any pending confirms will be lost.
Since Spring AMQP caches channels for reuse, downstream operations can cause the channel to be closed and the confirm lost.
For example:
#SpringBootApplication
public class So48518319Application {
public static void main(String[] args) {
SpringApplication.run(So48518319Application.class, args).close();
}
#Bean
public ApplicationRunner runner(RabbitTemplate template) {
return args -> {
template.setConfirmCallback((correlation, ack, cause) -> {
System.out.println(correlation + ":" + ack + " " + (cause == null ? "" : cause));
((MyCorrelationData) correlation).getLatch().countDown();
});
MyCorrelationData foo = new MyCorrelationData("foo");
MyCorrelationData bar = new MyCorrelationData("bar");
MyCorrelationData baz = new MyCorrelationData("baz");
template.convertAndSend("output", "output.foo", "foo", foo);
template.convertAndSend("output", "output.foo", "foo", bar);
template.convertAndSend("output", "output.foo", "foo", baz);
if (!foo.getLatch().await(10, TimeUnit.SECONDS)) {
throw new RuntimeException("Foo failed");
}
if (!bar.getLatch().await(10, TimeUnit.SECONDS)) {
throw new RuntimeException("Bar failed");
}
if (!baz.getLatch().await(10, TimeUnit.SECONDS)) {
throw new RuntimeException("Baz failed");
}
System.out.println("All good");
};
}
public static class MyCorrelationData extends CorrelationData {
private CountDownLatch latch = new CountDownLatch(1);
public MyCorrelationData(String id) {
super(id);
}
protected CountDownLatch getLatch() {
return this.latch;
}
protected void setLatch(CountDownLatch latch) {
this.latch = latch;
}
}
}
works well
CorrelationData [id=foo]:true
CorrelationData [id=bar]:true
CorrelationData [id=baz]:true
All good, but if I change it to
template.convertAndSend("output", "output.foo", "foo", foo);
template.convertAndSend("noutput", "output.foo", "foo", bar);
template.convertAndSend("noutput", "output.foo", "foo", baz);
we get
CorrelationData [id=foo]:false channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no exchange 'noutput' in vhost '/', class-id=60, method-id=40)
CorrelationData [id=bar]:false channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no exchange 'noutput' in vhost '/', class-id=60, method-id=40)
CorrelationData [id=baz]:false channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no exchange 'noutput' in vhost '/', class-id=60, method-id=40)
To avoid reusing the channel until the ack is received, you can use the template's invoke method; this prevents the channel from being reused for the bad sends:
#SpringBootApplication
public class So48518319Application {
public static void main(String[] args) {
SpringApplication.run(So48518319Application.class, args).close();
}
#Bean
public ApplicationRunner runner(RabbitTemplate template) {
return args -> {
template.setConfirmCallback((correlation, ack, cause) -> {
System.out.println(correlation + ":" + ack + " " + (cause == null ? "" : cause));
MyCorrelationData myCorrelation = (MyCorrelationData) correlation;
myCorrelation.getLatch().countDown();
myCorrelation.setAck(ack);
});
MyCorrelationData foo = new MyCorrelationData("foo");
MyCorrelationData bar = new MyCorrelationData("bar");
MyCorrelationData baz = new MyCorrelationData("baz");
boolean result1 = template.invoke(t -> {
t.convertAndSend("output", "output.foo", "foo", foo);
try {
if (!foo.getLatch().await(10, TimeUnit.SECONDS)) {
throw new RuntimeException("Foo failed");
}
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return foo.isAck();
});
boolean result2 = template.invoke(t -> {
t.convertAndSend("noutput", "output.foo", "bar", bar);
try {
if (!bar.getLatch().await(10, TimeUnit.SECONDS)) {
throw new RuntimeException("Bar failed");
}
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return bar.isAck();
});
boolean result3 = template.invoke(t -> {
t.convertAndSend("noutput", "output.foo", "baz", baz);
try {
if (!baz.getLatch().await(10, TimeUnit.SECONDS)) {
throw new RuntimeException("Baz failed");
}
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return baz.isAck();
});
System.out.println("All done: " + result1 + "," + result2 + "," + result3);
};
}
public static class MyCorrelationData extends CorrelationData {
private final CountDownLatch latch = new CountDownLatch(1);
private volatile boolean ack;
public MyCorrelationData(String id) {
super(id);
}
public CountDownLatch getLatch() {
return this.latch;
}
public boolean isAck() {
return this.ack;
}
public void setAck(boolean ack) {
this.ack = ack;
}
}
}
with
CorrelationData [id=foo]:true
CorrelationData [id=bar]:false channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no exchange 'noutput' in vhost '/', class-id=60, method-id=40)
CorrelationData [id=baz]:false channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no exchange 'noutput' in vhost '/', class-id=60, method-id=40)
All done: true, false, false
But that defeats the benefit of using publisher confirms, unless you do the sends on separate threads.
Bottom line is "don't send messages to non-existent exchanges if you are using confirms".

Related

RabbitTemplate's setChannelTransacted flag causes message being not delivered to queue

Given I have application with AMQP anonymous queue and fanout exchange:
#Bean
public Queue cacheUpdateAnonymousQueue() {
return new AnonymousQueue();
}
public static final String CACHE_UPDATE_FANOUT_EXCHANGE = "cache.update.fanout";
#Bean
FanoutExchange cacheUpdateExchange() {
return new FanoutExchange(CACHE_UPDATE_FANOUT_EXCHANGE);
}
#Bean
Binding cacheUpdateQueueToCacheUpdateExchange() {
return bind(cacheUpdateAnonymousQueue())
.to(cacheUpdateExchange());
}
and Spring Integration flow:
#Bean
public IntegrationFlow cacheOutputFlow() {
return from(channelConfig.cacheUpdateOutputChannel())
.transform(objectToJsonTransformer())
.handle(outboundAdapter())
.get();
}
And I use outbound adapter:
public MessageHandler outboundAdapter() {
rabbitTemplate.setChannelTransacted(true);
return outboundAdapter(rabbitTemplate)
.exchangeName(CACHE_UPDATE_FANOUT_EXCHANGE)
.get();
}
I can see in logs:
o.s.amqp.rabbit.core.RabbitTemplate: Executing callback on RabbitMQ Channel: Cached Rabbit Channel: AMQChannel(amqp://guest#127.0.0.1:5672/,4), conn: Proxy#40976c4b Shared Rabbit Connection: SimpleConnection#1cfaa28d [delegate=amqp://guest#127.0.0.1:5672/, localPort= 56042]
o.s.amqp.rabbit.core.RabbitTemplate: Publishing message on exchange [cache.update.fanout], routingKey = []
but message is not delivered to queue bound to cache.update.fanout exchange.
When I set rabbitTemplate.setChannelTransacted(false); in outbound adapter, then I can see in logs:
o.s.amqp.rabbit.core.RabbitTemplate : Executing callback on RabbitMQ Channel: Cached Rabbit Channel: AMQChannel(amqp://guest#127.0.0.1:5672/,1), conn: Proxy#11a1389d Shared Rabbit Connection: SimpleConnection#444c6abf [delegate=amqp://guest#127.0.0.1:5672/, localPort= 56552]
o.s.amqp.rabbit.core.RabbitTemplate : Publishing message on exchange [cache.update.fanout], routingKey = []
and message is delivered to queue.
Why is message not delivered in first case?
Why doesn't RabbitTemplate indicate something?
Your logs have different exchange names; I just tested it like this...
#SpringBootApplication
public class So60993877Application {
public static void main(String[] args) {
SpringApplication.run(So60993877Application.class, args);
}
#Bean
public Queue cacheUpdateAnonymousQueue() {
return new AnonymousQueue();
}
public static final String CACHE_UPDATE_FANOUT_EXCHANGE = "cache.update.fanout";
#Bean
FanoutExchange cacheUpdateExchange() {
return new FanoutExchange(CACHE_UPDATE_FANOUT_EXCHANGE);
}
#Bean
Binding cacheUpdateQueueToCacheUpdateExchange() {
return BindingBuilder.bind(cacheUpdateAnonymousQueue())
.to(cacheUpdateExchange());
}
#RabbitListener(queues = "#{cacheUpdateAnonymousQueue.name}")
public void listen(String in) {
System.out.println(in);
}
#Bean
public ApplicationRunner runner(RabbitTemplate template) {
return args -> {
template.convertAndSend(CACHE_UPDATE_FANOUT_EXCHANGE,
cacheUpdateAnonymousQueue().getName(), "foo");
template.setChannelTransacted(true);
template.convertAndSend(CACHE_UPDATE_FANOUT_EXCHANGE,
cacheUpdateAnonymousQueue().getName(), "bar");
};
}
}
With no problems.
foo
bar
With confirms and returns enabled:
#Bean
public ApplicationRunner runner(RabbitTemplate template) {
template.setReturnCallback((message, replyCode, replyText, exchange, routingKey) ->
LOG.info("Return: " + message));
template.setConfirmCallback((correlationData, ack, cause) ->
LOG.info("Confirm: " + correlationData + ": " + ack));
return args -> {
template.convertAndSend(CACHE_UPDATE_FANOUT_EXCHANGE, cacheUpdateAnonymousQueue().getName(),
"foo", new CorrelationData("foo"));
// template.setChannelTransacted(true);
template.convertAndSend(CACHE_UPDATE_FANOUT_EXCHANGE, cacheUpdateAnonymousQueue().getName(),
"bar", new CorrelationData("bar"));
template.convertAndSend("missingExchange", cacheUpdateAnonymousQueue().getName(), "baz",
new CorrelationData("baz"));
Thread.sleep(5000);
};
}

onMessageReceived method is not called, when app is not open

I have implemented FCM in my app, and I need to pass some data from Firebase service to Activity. I have implemented the following code, which works fine, when the app is in foreground(open). When the app is killed or in background, onMessageReceived method is not called, and the launcher activity is loaded while click on the push notification. Also, when the app is open, push message is blank. Kindly advise what I have done wrong. FYI, from backend, they are sending data payload, not notification.
public class FirebaseMessagingService extends com.google.firebase.messaging.FirebaseMessagingService {
public FirebaseMessagingService() {
}
private static final String TAG = com.google.firebase.messaging.FirebaseMessagingService.class.getSimpleName();
public static String CHAT_PUSH_NOTIFICATION_INTENT = "chatPushNotificationIntent";
private PreferencesManager preferencesManager;
#Override
public void onNewToken(String s) {
super.onNewToken(s);
Log.e("push token >>", s);
String reliableIdentifier = FirebaseInstanceId.getInstance().getId();
FCMPreferencesManager pref = FCMPreferencesManager.getInstance(this);
if (pref != null) {
pref.setStringValue(FCMPreferencesManager.FCM_KEY_VALUE, s);
pref.setStringValue(FCMPreferencesManager.DEVICE_ID, reliableIdentifier);
}
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
try {
preferencesManager = PreferencesManager.getInstance(this);
int userId = preferencesManager.getIntValue(PreferencesManager.LOGIN_USER_ID);
Log.e("onMessage received >>", "inside service");
Log.e("userId >>", userId + "");
if (userId > 0) {
Log.e("remote message >>", remoteMessage.getNotification().getBody() + "");
if (remoteMessage.getData().size() > 0) {
Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());
try {
JSONObject json = new JSONObject(remoteMessage.getData().toString());
handleDataMessage(json);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void classApprovedNotification(int jobId, String stage) {
if (!Utils.isAppIsInBackground(getApplicationContext())) {
Intent pushNotification = new Intent(Constants.PUSH_NOTIFICATION_INTENT);
pushNotification.putExtra("jobId", jobId);
pushNotification.putExtra("stage", stage);
LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);
}
}
private void handleDataMessage(JSONObject json) {
try {
Log.e("total json >> ", json.toString());
JSONObject data = json.optJSONObject("data");
Log.e("data >> ", data.toString());
String title = data.optString("title");
String message = data.optString("message");
Log.e("title >>", title);
Log.e("message >>", message);
localNotification(data, title, message, false);
} catch (Exception e) {
Log.e(TAG, "Json Exception: " + e.getMessage());
}
}
private void localNotification(JSONObject data, String title, String message, boolean isSendBird) {
int type = 0, groupId = 0, classId = 0, jobId = 0;
String stage = "";
int notificationId = (int) System.currentTimeMillis();
int userId = preferencesManager.getIntValue(PreferencesManager.LOGIN_USER_ID);
String className = "", fileName = "";
if (data != null) {
jobId = data.optInt("job_id");
stage = data.optString("stage", "");
}
Log.e("jobId in service >>", jobId + "");
Log.e("stage in service >>", stage);
Intent intent = new Intent(FirebaseMessagingService.this, VendorHomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.putExtra("jobId", jobId);
intent.putExtra("stage","stage");
int requestID = (int) System.currentTimeMillis();
final PendingIntent resultPendingIntent =
PendingIntent.getActivity(
this,
requestID,
intent,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
);
String channelId = "";
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.fyxt_logo)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(resultPendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
/* NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(this);*/
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(notificationId /* ID of notification */, notificationBuilder.build());
try {
PowerManager.WakeLock screenLock = null;
if ((getSystemService(POWER_SERVICE)) != null) {
screenLock = ((PowerManager) getSystemService(POWER_SERVICE)).newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "OOTUSER:WAKE");
screenLock.acquire(10 * 60 * 1000L /*10 minutes*/);
screenLock.release();
}
} catch (Exception e) {
e.printStackTrace();
}
classApprovedNotification(jobId, stage);
}
}
In my Activity, I have the following code.
private BroadcastReceiver notificationReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
jobIdFromNotification = intent.getIntExtra("jobId", 0);
stageFromNotification = intent.getStringExtra("stage");
Log.e("jobIdFromNotification >>", jobIdFromNotification + "");
Log.e("stageFromNotification >>", stageFromNotification);
prefManager.setIntValue(PreferencesManager.JOB_ID_IN_PREF, jobIdFromNotification);
prefManager.setStringValue(PreferencesManager.JOB_STAGE_IN_PREF, stageFromNotification);
classApprovedViewUpdate();
}
};
private void classApprovedViewUpdate() {
if (jobIdFromNotification > 0) {
fragmentInteractionCallback = (BaseFragment.FragmentInteractionCallback) this;
Log.e("inside push receiver update ", "sfs");
if (stageFromNotification.trim().equalsIgnoreCase(Constants.STAGE_TICKET_APPROVAL)) {
sendActionToActivity(ACTION_CREATE_MAINTENANCE_REQUEST, currentTab, true, fragmentInteractionCallback);
}
}
}
Edit:
data payload:
{
"data": {
"type": 0,
"job_id": 123,
"stage": "STAGE_TICKET_APPROVAL",
}

How to render a StreamObserver in WebUI (ktor + freemarker)

How to handle the output of a StreamObserver in freemarker ?
I have the following controller code so as to subscribe to a stream channel.
else -> {
try {
//jsonResponse = gnhc.getRequestJsonOutput(pathlist,pretty = true)
jsonResponseRaw = gnhc.subscribev1(pathlist, subId, writer).toString()
jsonResponse = jsonResponseRaw
application.log.debug("SDN_JSON_PROCESSOR: ${jsonResponse}")
} catch (e: Exception) {
jsonResponse = e.toString()
application.log.error("Failed to set channel", e)
} finally {
gnhc.shutdownNow()
}
}
}
call.respond(FreeMarkerContent("subscribe.ftl", mapOf("hostname" to hostname, "port" to port, "cmd" to cmd, "result" to jsonResponse,"rawresult" to jsonResponseRaw, "pathlist" to pathlist, "error" to error), etag = "e"))
}
The Observer is declared here:
try {
// simple observer without writer and subId
val sr: StreamObserver<Gnmi.SubscribeRequest> = stub.subscribe(GnmiStreamObserver(this))
// Writer + Id
//val sr: StreamObserver<Gnmi.SubscribeRequest> = stub.subscribe(StreamResponseWriter(_path,_id,_writer))
sr.onNext(subRequest)
waitCompleted()
sr.onCompleted()
}

How to get Messages by the consumer according to priority of the messages set by the publishers RabbitMQ

I have publish messages with some priority set for a single consumer(i.e single consumer that may receive messages according to message priority).
What i want is to get that messages and print them according to the message priority on the consumer side. Hey guys Help me out in this !
public class Send extends Thread {
int priority;
String name = "";
String app_type = "";
private static final String EXCHANGE_NAME = "topic_exchange";
public void run()
{
ConnectionFactory connFac = new ConnectionFactory();
connFac.setHost("localhost");
try {
Connection conn = connFac.newConnection();
Channel channel = conn.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME,
BuiltinExchangeType.TOPIC);
for(int j=1; j<=200; j++)
{
randomWait();
int random = (int)(Math.random() * 10 + 1);
String routingKey = j+"."+"update"+"."+app_type;
String msg = name;
channel.basicPublish(EXCHANGE_NAME, routingKey, new
AMQP.BasicProperties.Builder()
.contentType("text/plain")
.deliveryMode(2)
.priority(priority)
.build(),
msg.getBytes("UTF-8"));
System.out.println("Sent " + routingKey + " : " + msg +
" "+" Priority : "+priority);
}
channel.close();
conn.close();
} catch (IOException ex) {
Logger.getLogger(Send.class.getName()).log(Level.SEVERE, null,
ex);
System.out.println("Exception1 :--"+ex);
} catch (TimeoutException ex) {
Logger.getLogger(Send.class.getName()).log(Level.SEVERE, null,
ex);
System.out.println("Exception 2:--"+ex);
}
}
void randomWait()
{
try {
Thread.currentThread().sleep((long)(200*Math.random()));
} catch (InterruptedException x) {
System.out.println("Interrupted!");
}
}
public static void main(String[] args) {
// TODO code application logic here
Send test1 = new Send();
test1.name = "Hello ANDROID";
test1.app_type = "ANDROID";
test1.priority = 10;
Send test2 = new Send();
test2.name = "Hello ANDROID";
test2.app_type = "ANDROID";
test2.priority = 5;
test1.start();
test2.start();
}
}
In the above code I have use thread to pass the priority and message value and started the both the thread at the same time to publish messages with different priorities. I have set the priority value in the AMQ Builder.
The queue has to be configured to support priority.

Client and Server UDP transport layer

I need to send a message saying "Hi" from client to a server, the server will reply back to the client adding to the received message "Received", once the client receives this new message it will send this to another server and that server will add another message to the received message saying "Replied". So in the end the client will receive the message "Hi Received Replied".
Client code:
public class UDPClient{
public static void main(String args[]) {
// args[0] = message to be sent to the server;
// args[1] = IP address of the server
DatagramSocket aSocket=null;
try {
aSocket=new DatagramSocket();
byte [] m = args[0].getBytes();
InetAddress aHost = InetAddress.getByName(args[1]);
int serverPort = 6789;
DatagramPacket request = new DatagramPacket(m,args[0].length(), aHost, serverPort);
aSocket.send(request);
byte[] buffer = new byte[1000];
DatagramPacket reply = new DatagramPacket(buffer,buffer.length);
aSocket.receive(reply);
System.out.println("Reply: " + new String(reply.getData(), 0, reply.getLength()));
}catch (SocketException e){System.out.println("Socket: " + e.getMessage());
}catch (IOException e){System.out.println("IO: " + e.getMessage());
}finally {
if(aSocket != null) aSocket.close();
}
}
}
Server Code:
public class UDPServer{
public static void main(String args[]) {
DatagramSocket aSocket = null;
try{
aSocket = new DatagramSocket(6789);
byte[] buffer = new byte[1000];
while(true){
DatagramPacket request = new DatagramPacket(buffer,buffer.length);
aSocket.receive(request);
System.out.println("Server is ready and waiting for requests ... ");
DatagramPacket reply = new DatagramPacket(request.getData(), request.getLength(),request.getAddress(), request.getPort());
}
}catch (SocketException e){System.out.println("Socket: " + e.getMessage());
}catch (IOException e) {System.out.println("IO: " + e.getMessage());
}finally {
if(aSocket != null) aSocket.close();
}
}
}