[Socket] Maly problem z odbiorem wiadomosci - CHAT

0

Czesc
Chcialem napisac prostego chata z uzyciem gniazd i napotkalem problem przy implementacji odbioru wiadomosci od serwera przez aplikacje klienta, tzn troche sie juz w tym "pogubilem" :-(

Ma to wygladac tak:

Serwer (To dziala OK)

  • klikamy utworz port
  • klikamy nasluchuj
  • tworzony jest watek nasluchujacy polaczenia z klientem
  • w momencie gdy klient sie przylaczy tworzony jest kolejny watek obslugujacy go tzn. Odbierana jest wiadomosc od klienta i wysylana jest do niego ta sama poprzedzona slowem "Echo (wiadomosc od klienta)"

Klient ( tu sa problemy)

  • klikamy setIP (ustawia IP serwera nasluchujacego)
  • klikamy setName (jakas nazwa dla klienta)
  • na dole wpisujemy wiadomosc i klikamy Send
  • w momencie klikniecia Send uruchamiany jest nowy watek i tam nastepuje wyslanie informacji do klienta.
    --- do tej pory jest OK ---
  • PROBLEM mam z implementacja mechanizmu nasluchujacego , sprawdzajacego czy serwer nie odeslal nam jakiej wiadomosci. Mam klase implementujaca Runnable i w jej metodzie run() jest potencjalny kod mogacy to obsluzyc tylko niewiem jak to dokladnie zrobic bo nasluch jak przy aplikacji serwera jest chyba nie mozliwy, torszke sie w tym pogubilem. Mam prosbe aby jesli ktos ma chwilke czasu zeby mi podpowiedzial co i gdzie robie zle albo czego nie robie :-)

PS. Wrzucam kompletny kodzik obu aplikacyjek:

SERWER:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */




import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;


public class Server {
	public static void main (String[] args)
	{
		ServerFrame frame = new ServerFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
}
class ServerFrame extends JFrame
{
	public ServerFrame()
	{
		setSize(500,500);
		setTitle("Server");
		panel = new JPanel();
		panel.setLayout(null);
		label_expect = new JLabel("Bezczynny");
		label_expect.setBounds(10, 10, 100, 25);
		panel.add(label_expect);
		button_port = new JButton("Utworz port");
		button_port.setBounds(120, 10, 120, 25);
		button_port.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent event)
			{
				button_port.setEnabled(false);
				label_expect.setText("Port Utworzony...");
				/*
				 * Jednorazowe utworzenie
				 * portu Servera
				 */
				try
				{
					ss = new ServerSocket(2025);
				}
				catch (IOException e)
				{
					e.printStackTrace();
				}				
			}
		});
		panel.add(button_port);
		button_message = new JButton("Uruchom nasluchiwanie");
		button_message.setBounds(200, 410, 270, 25);
		panel.add(button_message);
		button_message.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent event)
			{
				
					/*
					 * Oczekiwanie na polczonie do portu servera.
					 * W nowym watku Serwer czeka na przylaczenie sie klienta
					 */
					new Thread(new Runnable(){

						@Override
						public void run() 
						{
							button_message.setText("Nasluchuje....");
							button_message.setEnabled(false);
							try 
							{
								/*
								 * Jesli klient sie przylaczy 
								 * to w nowym watku zostanie obslużony
								 */
								while(true)
								{	
									incoming = ss.accept(); // przylaczenie klienta
									label_expect.setText("Polaczono...");
									textArea.setText("Wszystko OK\n");
									Runnable r = new ClientThread(incoming); //obsluga klienta jesli polaczono
									Thread t = new Thread(r);
									t.start();
								}
							}
							catch (UnknownHostException e) 
							{
								e.printStackTrace();
							}
							catch (IOException e) 
							{
								e.printStackTrace();
							}
							finally
							{
								try 
								{
									incoming.close();
								} 
								catch (IOException e) 
								{
									e.printStackTrace();
								}
							}
						}
						}).start();					
				}			
		});

		textArea = new JTextArea(200,200);
		JScrollPane scroll = new JScrollPane(textArea);
		scroll.setBounds(10, 43, 450, 350);
		panel.add(scroll);
		add(panel);
	}

	/*
	 * Klasa odpowiedzialana za obsluge polaczenia z klientem, czyli odebranie
	 * wiadomosci od niego. Jest uruchamiana w moemencie nawiazania polaczenia 
	 * z klientem.
	 */
	class ClientThread implements Runnable
	{
		public ClientThread(Socket i)
		{
			this.i = i;
		}
		public void run()
		{
				try
				{
					/* strumien wejsciowy do serwera
					 * (strumien wyjsciowy klienta)
					 */ 				
					InputStream inStream = i.getInputStream();
					BufferedReader in = new BufferedReader(new InputStreamReader(inStream));		        
					/*
					 * Strumien wyjsciowy od serwera do klienta
					 * (strumien wejsciowy klienta)
					 */
					OutputStream outStream = i.getOutputStream();
					Writer writer = new BufferedWriter(new OutputStreamWriter(outStream));
						
					String line = in.readLine();  //pobranie wiadomosci od klienta
					textArea.setText(line);
					incoming = ss.accept();

					writer.append("Echo" + line); //wyslanie wiadomosci do klienta (wiadomosc odebrana poprzedzona "Echo")
					writer.close();

					in.close();
					i.close();

				}
				catch (IOException e)
				{
					e.printStackTrace();
				}				
			}
	
		private Socket i;
	}
	private JPanel panel;
	private JTextArea textArea;
	private JButton button_message;
	private JButton button_port;
	private JLabel label_expect;
	private String name;
	private JScrollPane scroll;
	private ServerSocket ss;
	private Socket incoming;
}

KLIENT



import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import javax.swing.JFrame;


public class Client {
	public static void main (String[] args)
	{
		ClientFrame frame = new ClientFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
}

class ClientFrame extends JFrame
{
	public ClientFrame()
	{
		setSize(500,500);
		setTitle("Klient");
		panel = new JPanel();
		panel.setLayout(null);
		label_ip = new JLabel("IP serwera :");
		label_ip.setBounds(10, 10, 70, 25);
		panel.add(label_ip);
		text_ip = new JTextField(15);
		text_ip.setBounds(90, 10, 80, 25);
		text_ip.setText("127.0.0.1");
		panel.add(text_ip);
		button_ip = new JButton("set IP");
		button_ip.setBounds(190, 10, 80, 25);
		button_ip.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent event)
			{
				/*
				 * Pobranie adresu ip serwera
				 */
				server_ip = text_ip.getText();
				text_ip.setEditable(false);
				button_ip.setEnabled(false);								
			}
		});
		panel.add(button_ip);
		text_name = new JTextField(20);
		text_name.setBounds(280, 10, 80, 25);
		text_name.setText("Klient");
		panel.add(text_name);
		button_name = new JButton("Set Name");
		button_name.setBounds(370, 10, 100, 25);
		panel.add(button_name);

		button_name.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent event)
			{
				name = text_name.getText();
				text_name.setEditable(false);
				button_name.setEnabled(false);
			}
		});
		label_message = new JLabel("Text:");
		label_message.setBounds(10, 410, 50, 25);
		panel.add(label_message);

		text_message = new JTextField(15);
		text_message.setBounds(40, 410, 330, 25);
		panel.add(text_message);

		button_message = new JButton("Send");
		button_message.setBounds(400, 410, 70, 25);
		panel.add(button_message);
		button_message.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent event)
			{				
				/*
				 * Watek odpowiedzialny za wysylanie informacji do serwera
				 */
				Runnable r = new SendMessage(s); 
				Thread t = new Thread(r);
				t.start();
			}
		});
		textArea = new JTextArea(200,200);
		JScrollPane scroll = new JScrollPane(textArea);
		scroll.setBounds(10, 43, 450, 350);
		panel.add(scroll);
		add(panel);
	}
	class SendMessage implements Runnable
	{
		SendMessage(Socket i)
		{
			this.i = i;
		}
		public void run()
		{
			try
			{		
					i = new Socket(server_ip,2025);
					//-------------------- wyslanie informacji do serwera
				    OutputStream outputStream = i.getOutputStream();
				    Writer writer = new BufferedWriter(new OutputStreamWriter(outputStream));
				    String line = text_message.getText();
				    //textArea.setText(textArea.getText() + "\n" + name + "> " + line);
				    writer.append(name + "> " + line);
				    writer.close();
				    i.close();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		
		private Socket i;
	}
	class ReciveMessage implements Runnable
	{
		ReciveMessage(Socket i)
		{
			this.i = i;
		}
		@Override
		public void run() 
		{
			InputStream inStream = null;
			BufferedReader in = null;
			try 
			{
				inStream = i.getInputStream();
				in = new BufferedReader(new InputStreamReader(inStream));		        
				String line = in.readLine();
				textArea.setText("dupka echa");
				in.close();
				i.close();
			} 
			catch (IOException e)
			{
				e.printStackTrace();
			}			
		}
		private Socket i;
	}
	private JPanel panel;
	private JTextArea textArea;
	private JButton button_message;
	private JButton button_ip;
	private JLabel label_message;
	private JLabel label_ip;
	private JTextField text_message;
	private JTextField text_ip;
	private JTextField text_name;
	private JButton button_name;
	private String name;
	private JScrollPane scroll;
	private String server_ip;
	private Socket s;
}
0

metoda sprawdzająca odebranie wiadomości od serwera?
A nie możesz po prostu wyświetlać wiadomości, które przychodzą z serwera w oknie komunikatora?

generalnie potrzebne są ci klasy np. PrintStream (do wysyłania) i BufferedReader (odbieranie) po obu stronach, tzn na serwerze i u klienta.
Gdy klient nawiąże już połączenie z serwerem to wysyła do niego wiadomość. Ten ją odbiera i odsyła - a na koniec odbiera ją klient... i tak w kółko.
U klienta do odbierania i wysyłania wiadomości mogą służyć osobne wątki.
Na serwerze, tak jak napisałeś, musi być tworzony osobny wątek dla każdego połączenia = klienta, a w nim obsługa wiadomości.

0

generalnie to co jest juz zaimplementowane to na serwerze wyglada tak

while(true)
{
      if(klient sie polaczyl)     // metoda accept()
      {
            Uruchom Nowy Watek i go obsluz 
      }
      
}

Klient wyglada tak

if( uzytkownik kliknal wyslij wiadomosc do serwera)
{
     uruchom nowy watek
     nawiaz polaczenie
     wyslij wiadomosc
     zakoncz polaczenie
}

i teraz chcialbym aby w tle "byl sobie taki watek" ktory caly czas laczy sie z serwerem i sprawdza czy "ten" mu nic nie przysyla jesli tak to obsluguje odebranie wiadomosci i zamyka polaczenie. Niewiem czy ja w ogóle dobrze to sobie wymyslilem bo cos mi sie wydaje ze nie do konca :/

0
szu napisał(a)

metoda sprawdzająca odebranie wiadomości od serwera?
A nie możesz po prostu wyświetlać wiadomości, które przychodzą z serwera w oknie komunikatora?

Szu wlasnie o to mi chodzi zeby wyswietlac te wiadomosci ale to musze jakos sprawdzic czy one sa, dlatego potrzebuje chyba jeszcze jednego watku ktory mi tego bedzie nasluchiwal?

0

Tak.

1 użytkowników online, w tym zalogowanych: 0, gości: 1