# Java Netzwerk Chatprogramm programmieren



## utos (19. Juni 2010)

Guten Abend Buffis,

Ich verzweifle ein bisschen an meinem Informatik Projekt.
Wir hatten freie Themenwahl und ich hab mich aus Interesse einfach mal an Java gewagt, doch nun gehts nicht mehr vorran.
Ich hatte viele Projektideen, aber die haben alle nicht geklappt.
Ich möchte jetzt einen Netzwerkchat programmieren, mit dem ich von meinem PC eine Nachricht absende und die auf einem anderem Rechner im Netzwerk ankommt.

Also quasi Client zu Client.

Es soll keinen Schnick Schnack haben, sondern einfach nur einfach und übersichtlich sein. 
Ich habe mir Tutorials angeguckt und dort sieht das alles ziemlich kompliziert aus.
Ist das für Einsteiger geeignet, oder ist es zu schwer?

Was könnte man sonst mit Java programmieren, falls das zu schwer ist?

Leider habe ich nur noch bis Donnerstag Zeit, weil alleine Java überhaupt ein bisschen zu verstehen, hat einfach viel Zeit gekostet 


			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Ich hoffe, irgendwer kann mir weiterhelfen


----------



## WR^Velvet (20. Juni 2010)

Hmm, in wiefern denn Einsteiger?
Also Java ist schon harter tobak, dann noch nen Chat programmieren.
Bis Donnerstag ist dazu schon verdammt knapp.
Hast du irgend welche Vorgaben? Gibt garantiert 1000 andere Sachen die wesentlich einfacher in der kurzen zeit zu realisieren sind.


----------



## Rethelion (20. Juni 2010)

Einen Chat stelle ich mir auch schwer vor, allein schon deswegen weil ich noch nie was netzwerkfähiges programmiert habe^^
Wie anspruchsvoll muss das Programm denn sein?


----------



## Klos1 (20. Juni 2010)

Also, an und für sich sollte es nicht so schwer sein. Ich kann dir nur zeigen, wie es in etwa in C# aussehen könnte. Ist jetzt nur so auf die Schnelle zusammengestöpselt und kein vollerwertiger Chat.
Ich denke, dass es mit der Java-Klassenbibliothek ähnlich einfach ist. Ich denke ja mal, dass du es nicht webbasierend machen willst, sondern ein client- und ein serverprogramm haben willst. So habe ich es verstanden.
Der Server könnte so in etwa aussehen:


```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace ServerApp
{
	class Program
	{
 	static void Main(string[] args)
 	{
 	Server myServer = new Server(IPAddress.Any, 5000);
 	}
	}
	public class Server
	{
 	private TcpListener _tcpListener;
 	private ASCIIEncoding _encoder;

 	public Server(IPAddress address, int port)
 	{
 	_encoder = new ASCIIEncoding();
 	//Tcp Listener an Port binden. Akzeptiert werden alle IP's
 	_tcpListener = new TcpListener(address, port);
 	//Listener starten
 	StartListener();
 	}
 	public void StartListener()
 	{
 	_tcpListener.Start();

 	Console.WriteLine("Server is listening on port 5000");
 	
 	//Listener hört nun auf Port 5000

 	//Endlosschleife. Sobald ein Client connected erstellen wir nen Thread und
 	//binden ihn über einen Delegaten (welche es in Java nicht gibt^^) an die Methode
 	//welche den request abarbeitet
 	while (true)
 	{
 	//Client hat connected
 	TcpClient myclient = _tcpListener.AcceptTcpClient();
 	
 	//Wir wickeln den request in einen separaten Thread ab
 	Thread cThread = new Thread(new ParameterizedThreadStart(ClientConnected));
 	cThread.Start(myclient);
 	}
 	}
 	private void ClientConnected(object c)
 	{
 	//den connectenden client holen und das stream objekt besorgen
 	TcpClient tcpClient = (TcpClient)c;
 	NetworkStream clientStream = tcpClient.GetStream();

 	byte[] buffer = new byte[1024];
 	//zählt die gelesenen bytes
 	int i4byteCount = 1;

 	while (i4byteCount > 0)
 	{
 	try
 	{
 	//bytes einlesen
 	i4byteCount = clientStream.Read(buffer, 0, 1024);
 	}
 	catch
 	{
 	//fehler
 	break;
 	}

 	_encoder = new ASCIIEncoding();
 	Console.WriteLine(_encoder.GetString(buffer, 0, i4byteCount));
 	Console.ReadLine();
 	}
 	}
	}
}
```

Sobald der nun gestartet ist, könntest du mit wenige Zeilen einen String an den Server schicken, welcher diesen dann an der Console anzeigen sollte. Zum Beispiel so:


```
TcpClient c = new TcpClient();

 	IPEndPoint sEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5000);

 	c.Connect(sEndPoint);

 	NetworkStream cStream = c.GetStream();

 	ASCIIEncoding encoder = new ASCIIEncoding();
 	byte[] buffer = encoder.GetBytes("Huhu, ich bins!");

 	cStream.Write(buffer, 0, buffer.Length);
 	cStream.Flush();
```

Solltest du das über das Netz schicken wollen, dann muss die Loopback-Adresse natürlich durch die IP ersetzt werden.
Keine Ahnung, ob es dir was hilft, aber so in der Art könnte es laufen.


----------



## Klos1 (21. Juni 2010)

Ich hab dir heute in der Arbeit mal eine kleine Beispielsanwendung zusammengestöpselt. Sie ist noch nicht ganz fertig, funktioniert im großen und ganzen schon. Ist halt etwas schlampig. 


			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        


Es gibt eine Server-Application, die gestartet werden muss. Zu Anfang gibt man einfach nur den Port ein, auf den diese lauschen soll. Der Server ist eine reine Consolen-Anwendung. Mehr braucht es ja auch nicht.
Die Client-Anwendung ist eine Windows Forms - Anwendung. Nachdem der Server gestartet ist, kann man sich mit dem Client connecten. Es können theoretisch beliebig viele Clients zum Server connecten.
Die verbundenen Sockets werden serverseitig in einem Dictionary verwaltet.

Der Server sendet alles quasi als Broadcoast an jeden Client, der aktuell verbunden ist. Jeder, der also mit dem Client verbunden ist, kann die Nachrichten von allen anderen Clients sehen, die auch verbunden sind.

Musst du eigentlich Java programmieren? Geht nicht auch C#? 


			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Hier mal der Server:


```
using System;
using System.Threading;
using System.Net.Sockets;
using System.Text;
using System.Collections;
using System.Text.RegularExpressions;
using System.Net;
using System.Collections.Generic;


namespace ServerApp
{

 public delegate void ClientAccepted(object sender, EventArgs e);
 
 class Program
 {
 	static void Main(string[] args)
 	{
 	//Request the port number the server should listen
 	Console.Write("Please enter the listening port: ");
 	Server myServer;

 	while (true)
 	{
 	string input = Console.ReadLine();
 	//Validate our input
 	Match match = Regex.Match(input, "\\d");
 	
 	if (match.Success)
 	{
 	try
 	{
 	//if valid we can create a new instance of our server
 	myServer = new Server(new TcpListener(IPAddress.Any, Convert.ToInt32(input)));
 	break;
 	}
 	catch
 	{
 	continue;
 	}
 	}
 	else
 	{
 	Console.Write("Please enter a valid port number: ");
 	}
 	}
 	myServer._clientAccepted+=new ClientAccepted(myServer__clientAccepted);
 	}

 	static void myServer__clientAccepted(object sender, EventArgs e)
 	{
 	
 	}
 	
 }
 public class Server
 {
 	private int _i4ConnectionCount = 0;
 	private TcpListener _sSocket;
 	private TcpClient _cSocket;
 	//stores all clients which are connected to the server
 	private Dictionary<string, TcpClient> _cSocketCol;
 	private ClientEventArgs _eventArgs;

 	public Server(TcpListener sSocket)
 	{
 	_cSocketCol = new Dictionary<string, TcpClient>();
 	_sSocket = sSocket;
 	//start the tcp listener
 	Thread listenerThread = new Thread(new ThreadStart(StartListening));
 	listenerThread.Start();
 	}
 	private void StartListening()
 	{
 	_sSocket.Start();
 	Console.WriteLine("Server started ...wait for client connection!");

 	//this loop is waiting for incoming connections. If a connection is established, make a new
 	//thread to handle the request, while the server is waiting for further requests
 	while (true)
 	{
 	_cSocket = _sSocket.AcceptTcpClient();
 	Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientRequest));
 	clientThread.Start(_cSocket);
 	}
 	}
 	private void OnClientAccpeted(ClientEventArgs e)
 	{ 
 	if(_clientAccepted != null)
 	_clientAccepted(this, e);
 	}

 	public event ClientAccepted _clientAccepted;

 	private void HandleClientRequest(object cSocket)
 	{
 	//get the client socket
 	TcpClient myClient = (TcpClient)cSocket;
 	
 	string clientMessage;
 	string name = null;
 	try
 	{
 	NetworkStream nStream = myClient.GetStream();
 	_i4ConnectionCount++;

 	while (myClient.Connected)
 	{

 	//the byte array stores the receiving data. To initialize our array, we need the
 	//size in case of the incoming bytes.
 	byte[] byteBuffer = new byte[(int)myClient.ReceiveBufferSize];

 	nStream.Read(byteBuffer, 0, byteBuffer.Length);
 	clientMessage = Encoding.UTF8.GetString(byteBuffer);
 	if (clientMessage.Substring(0, 13) == "disposeObject")
 	break;
 	int index = clientMessage.IndexOf("$");
 	if (index != -1)
 	{
 	name = clientMessage.Substring(0, index);
 	_eventArgs = new ClientEventArgs(name);
 	OnClientAccpeted(_eventArgs);

 	if (!_cSocketCol.ContainsKey(_i4ConnectionCount.ToString() + name))
 	_cSocketCol.Add(_i4ConnectionCount.ToString() + name, myClient);
 	}
 	foreach (TcpClient client in _cSocketCol.Values)
 	{
 	TcpClient tcpClient = (TcpClient)client;
 	NetworkStream ns = tcpClient.GetStream();
 	if (index != -1)
 	{
 	byte[] bBytesArray = Encoding.UTF8.GetBytes(name + " has joined the server...");
 	ns.Write(bBytesArray, 0, bBytesArray.Length);
 	}
 	else
 	{
 	ns.Write(byteBuffer, 0, byteBuffer.Length);
 	}
 	ns.Flush();
 	}
 	}
 	foreach (string key in _cSocketCol.Keys)
 	{
 	if (myClient == _cSocketCol[key])
 	{
 	_cSocketCol.Remove(key);
 	break;
 	}
 	}
 	myClient.Close();
 	}
 	catch
 	{ 
 	//an exception was thrown
 	}
 	}
 	public class ClientEventArgs : EventArgs
 	{
 	public ClientEventArgs(string user)
 	{
 	_sUser = user;
 	}
 	private string _sUser;
 	public string psUser
 	{
 	get { return _sUser; }
 	}
 	}
 }
}
```

Und hier wäre der Client:


```
using System;
using System.Windows.Forms;
using System.Text;
using System.Net.Sockets;
using System.Threading;

namespace ClientApp
{
 public partial class Form1 : Form
 {
 	TcpClient _cSocket;
 	NetworkStream _sStream;
 	string _rData = null;

 	public Form1()
 	{
 	InitializeComponent();
 	_cSocket = new TcpClient();
 	FillMandatoryFieldsWithDefaultValue();
 	tb_Message.KeyDown += new KeyEventHandler(tb_Message_KeyDown);
 	}

 	void tb_Message_KeyDown(object sender, KeyEventArgs e)
 	{
 	if (e.KeyCode == Keys.Return)
 	{
 	bt_send_Click(this, EventArgs.Empty);
 	}
 	}
 	/// <summary>
 	/// Method, which make the default network configuration
 	/// </summary>
 	private void FillMandatoryFieldsWithDefaultValue()
 	{
 	tb_Port.Text = "5000";
 	tb_ServerIP.Text = "127.0.0.1";
 	}
 	/// <summary>
 	/// Validate the mandatory fields
 	/// </summary>
 	/// <returns>true, if all settings are done. Otherwise return false</returns>
 	private bool PerformValidateSettings()
 	{
 	if (!string.IsNullOrEmpty(tb_Name.Text) && !string.IsNullOrEmpty(tb_ServerIP.Text)
 	&& !string.IsNullOrEmpty(tb_Port.Text))
 	return true;
 	return false;
 	}
 	private void WriteData()
 	{
 	if (this.InvokeRequired)
 	this.Invoke(new MethodInvoker(WriteData));
 	else
 	rtb_ChatContext.Text = rtb_ChatContext.Text + Environment.NewLine + " > " + _rData;
 	}

 	private void bt_Connect_Click(object sender, EventArgs e)
 	{
 	if (PerformValidateSettings())
 	{
 	if (!_cSocket.Connected)
 	_cSocket.Connect(tb_ServerIP.Text, Convert.ToInt32(tb_Port.Text));
 	
 	_sStream = _cSocket.GetStream();

 	byte[] outStream = Encoding.ASCII.GetBytes(tb_Name.Text + "$");
 	_sStream.Write(outStream, 0, outStream.Length);
 	_sStream.Flush();

 	Thread ctThread = new Thread(new ThreadStart(getMessage));
 	ctThread.Start();
 	}
 	else
 	{
 	MessageBox.Show("Please complete the settings to proceed!");
 	}
 	tb_Message.Focus();
 	}

 	private void bt_send_Click(object sender, EventArgs e)
 	{
 	byte[] outStream = Encoding.UTF8.GetBytes(tb_Name.Text + "%" + tb_Message.Text);
 	_sStream.Write(outStream, 0, outStream.Length);
 	_sStream.Flush();
 	tb_Message.Clear();
 	tb_Message.Focus();
 	}
 	private void getMessage()
 	{
 	while (_cSocket.Connected)
 	{
 	try
 	{
 	_sStream = _cSocket.GetStream();
 	int bufferSize = 0;
 	byte[] inStream;
 	bufferSize = _cSocket.ReceiveBufferSize;
 	inStream = new byte[bufferSize];
 	_sStream.Read(inStream, 0, inStream.Length);
 	string inputString = System.Text.Encoding.UTF8.GetString(inStream);
 	int index = inputString.IndexOf("%");
 	if (index != -1)
 	{
 	string name = inputString.Substring(0, index);
 	string test = inputString.Substring(index + 1);
 	_rData = name + ": " + inputString.Substring(index + 1);
 	}
 	else
 	{
 	_rData = inputString;
 	}
 	WriteData();
 	}
 	catch
 	{ 
 	//An exception was thorwn
 	}
 	}
 	}

 	private void Form1_FormClosing(object sender, FormClosingEventArgs e)
 	{
 	byte[] outStream = Encoding.UTF8.GetBytes("disposeObject");
 	_sStream.Write(outStream, 0, outStream.Length);
 	_sStream.Flush();
 	_sStream.Close();
 	_cSocket.Close();
 	}
 }
}
```

Und so sieht der Client aus:




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.


----------



## Sugarwarlock (22. Juni 2010)

da c# von java zu 80% kopiert ist und java dann die verbesserungen in c# auch übernommen hat, ist es total egal was du nimmst. nur eclipse und netbean sind nicht so toll wie vs2k10. aber nen chat hab ich relativ schnell geschrieben. einfach googlen gibt genut tutorials (hab meinen chat wieder gelöscht weil hdd crash).


----------

