android聊天室的聊天功能吧,先说说服务器端的代码及其功能吧
server.java : 负责服务器的界面,以及更服务器主线程ServerThread的启动,产生了BroadCast广播,产生ClientThread线程
ServerThread.java:服务器监听的端口线程,负责创建ServerSocket及监听是否有新的客户端连接,并记录客户端连接及需要发送的信息,产生了BroadCast广播
BroadCast.java: 服务器向客户端广播线程,负责向客户端发送消息,产生ClientThread线程
ClientThread.java:维持服务器和单个客户端的连接线程,负责接受客户端发来是信息
好了接着就看看他们的代码吧!!
1.server.java-------创建ServerThread对象启动run方法
package com.wang;
import java.awt.BorderLayout;
import javax.swing.*;
import java.awt.event.*;
public class Server extends JFrame implements ActionListener {
BorderLayout borderLayout1 = new BorderLayout();
BorderLayout borderLayout2 = new BorderLayout();
JPanel jPanel1 = new JPanel();
JPanel jPanel2 = new JPanel();
JButton jButton1 = new JButton();
JButton jButton2 = new JButton();
JScrollPane jScrollPane1 = new JScrollPane();
static JTextArea jTextArea1 = new JTextArea();
boolean bool = false , start = false ;
ServerThread serverThread;
Thread thread;
public Server() {
super ( "Server" );
getContentPane().setLayout(borderLayout1);
jButton1.setText("启动服务器" );
jButton1.addActionListener(this );
jButton2.setText("关闭服务器" );
jButton2.addActionListener(this );
this .getContentPane().add(jPanel1, java.awt.BorderLayout.NORTH);
jPanel1.add(jButton1);
jPanel1.add(jButton2);
jTextArea1.setText("" );
jPanel2.setLayout(borderLayout2);
jPanel2.add(jScrollPane1, java.awt.BorderLayout.CENTER);
jScrollPane1.getViewport().add(jTextArea1);
this .getContentPane().add(jPanel2, java.awt.BorderLayout.CENTER);
this .setSize( 400 , 400 );
this .setVisible( true );
}
public static void main(String[] args) {
Server sever = new Server();
sever.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == jButton1) {
serverThread = new ServerThread();
serverThread.start();
} else if (e.getSource() == jButton2) {
bool = false ;
start = false ;
serverThread.finalize();
this .setVisible( false );
}
}
}
2.ServerThread.java -----创建Broadcast对象,启动该线程,实现run方法后,不断的向客户端发送消息,ServerThread开启后,不断的获取新的客户端并监听是否发送消息
package com.wang;
import java.util.*;
import java.io.*;
import java.net.*;
public class ServerThread extends Thread
{
ServerSocket serverSocket;
public static final int PORT = 80 ;
Vector clients;
Vector messages;
BroadCast broadcast;
String ip;
InetAddress myIPaddress = null ;
public ServerThread() {
clients = new Vector();
messages = new Vector();
try {
serverSocket = new ServerSocket(PORT);
} catch (IOException E) {
}
try {
myIPaddress = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
System.out.println(e.toString());
}
ip = myIPaddress.getHostAddress();
Server.jTextArea1.append("服务器地址:" + ip + "端口号:"
+ String.valueOf(serverSocket.getLocalPort()) + "\n" );
broadcast = new BroadCast( this );
broadcast.start();
}
public void run() {
while ( true ) {
try {
Socket socket = serverSocket.accept();
System.out.println(socket.getInetAddress().getHostAddress());
ClientThread clientThread = new ClientThread(socket, this );
clientThread.start();
if (socket != null ) {
synchronized (clients) {
clients.addElement(clientThread);
}
}
} catch (IOException E) {
System.out.println("发生异常:" + E);
System.out.println("建立客户端联机失败!" );
System.exit(2 );
}
}
}
public void finalize() {
try {
serverSocket.close();
} catch (IOException E) {
}
serverSocket = null ;
}
}
3.BroadCast.java------
package com.wang;
import java.io.*;
public class BroadCast extends Thread {
ClientThread clientThread;
ServerThread serverThread;
String str;
public BroadCast(ServerThread serverThread) {
this .serverThread = serverThread;
}
public void run() {
while ( true ) {
try {
Thread.sleep(200 );
} catch (InterruptedException E) {
}
synchronized (serverThread.messages) {
if (serverThread.messages.isEmpty()) {
continue ;
}
str = (String) this .serverThread.messages.firstElement();
}
synchronized (serverThread.clients) {
for ( int i = 0 ; i < serverThread.clients.size(); i++) {
clientThread = (ClientThread) serverThread.clients
.elementAt(i);
try {
clientThread.out.writeUTF(str);
} catch (IOException E) {
}
}
this .serverThread.messages.removeElement(str);
}
}
}
}
4.ClientThread.java----获得Socket的输入输出流,向客户端接收或者发送数据
package com.wang;
import java.net.*;
import java.io.*;
public class ClientThread extends Thread
{
Socket clientSocket;
DataInputStream in = null ;
DataOutputStream out = null ;
ServerThread serverThread;
public ClientThread(Socket socket,ServerThread serverThread)
{
clientSocket=socket;
this .serverThread=serverThread;
try
{
in = new DataInputStream(clientSocket.getInputStream());
out = new DataOutputStream(clientSocket.getOutputStream());
}
catch (IOException e2)
{
System.out.println("发生异常" +e2);
System.out.println("建立I/O通道失败!" );
System.exit(3 );
}
}
public void run()
{
while ( true )
{
try
{
String message=in.readUTF();
synchronized (serverThread.messages)
{
if (message!= null )
{
serverThread.messages.addElement(message);
Server.jTextArea1.append(message+'\n' );
}
}
}
catch (IOException E){ break ;}
}
}
}
5.接着看看手机客户端的布局main.xml
xml version = "1.0" encoding = "utf-8" ?>
< LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
android:orientation = "vertical" >
< LinearLayout
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:orientation = "horizontal" >
< EditText
android:id = "@+id/username"
android:layout_width = "270dp"
android:layout_height = "wrap_content"
android:hint = "请输入用户名:"
android:maxLength = "10" >
EditText >
< Button
android:id = "@+id/LoginButton"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "登陆" />
LinearLayout >
< LinearLayout
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:orientation = "horizontal" >
< EditText
android:id = "@+id/ip"
android:layout_width = "270dp"
android:layout_height = "wrap_content"
android:digits = ".1234567890"
android:hint = "10.254.1.62" >
EditText >
< Button
android:id = "@+id/LeaveButton"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "退出" />
LinearLayout >
< EditText
android:id = "@+id/history"
android:layout_width = "fill_parent"
android:layout_height = "280dp" >
EditText >
< LinearLayout
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:orientation = "horizontal" >
< EditText
android:id = "@+id/message"
android:layout_width = "270dp"
android:layout_height = "wrap_content" >
EditText >
< Button
android:id = "@+id/SendButton"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "发送" />
LinearLayout >
LinearLayout >
6.接着看看手机客户端的实现ChatClientActivity.java
package com.wang;
import android.app.Activity;
import android.os.Bundle;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.sql.Date;
import java.text.SimpleDateFormat;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class ChatClientActivity extends Activity implements Runnable {
private EditText usernameEdit;
private EditText ipEdit;
private EditText historyEdit;
private EditText messageEdit;
private Button loginButton;
private Button sendButton;
private Button leaveButton;
private String username, ip, chat_txt, chat_in;
public static final int PORT = 80 ;
Socket socket;
Thread thread;
DataInputStream dataInputStream;
DataOutputStream dataOutputStream;
boolean flag = false ;
public void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
this .requestWindowFeature(Window.FEATURE_NO_TITLE);
this .getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
usernameEdit = (EditText) findViewById(R.id.username);
ipEdit = (EditText) findViewById(R.id.ip);
historyEdit = (EditText) findViewById(R.id.history);
messageEdit = (EditText) findViewById(R.id.message);
loginButton = (Button) findViewById(R.id.LoginButton);
sendButton = (Button) findViewById(R.id.SendButton);
leaveButton = (Button) findViewById(R.id.LeaveButton);
loginButton.setOnClickListener(listener);
sendButton.setOnClickListener(listener);
leaveButton.setOnClickListener(listener);
}
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.LoginButton:
if (flag == true ) {
Toast.makeText(ChatClientActivity.this , "亲,你已经登陆过啦!!!" ,
Toast.LENGTH_LONG).show();
return ;
}
username = usernameEdit.getText().toString();
ip = ipEdit.getText().toString();
if (username != "" && username != null && username != "用户名输入"
&& ip != null ) {
try {
socket = new Socket(ip, PORT);
dataInputStream = new DataInputStream(socket
.getInputStream());
dataOutputStream = new DataOutputStream(socket
.getOutputStream());
Date now = new Date(System.currentTimeMillis());
SimpleDateFormat format = new SimpleDateFormat(
"hh:mm:ss" );
String nowStr = format.format(now);
dataOutputStream.writeUTF("└(^o^)┘: " + username
+ " : " + nowStr + " 上线啦!" );
} catch (IOException e1) {
System.out.println("抱歉连接不成功!!!" );
}
thread = new Thread(ChatClientActivity. this );
thread.start();
flag = true ;
}
break ;
case R.id.SendButton:
if (flag == false ) {
Toast.makeText(ChatClientActivity.this , "亲,你还没登录,请先登录!" ,
Toast.LENGTH_LONG).show();
return ;
}
chat_txt = messageEdit.getText().toString();
if (chat_txt != null ) {
Date now = new Date(System.currentTimeMillis());
SimpleDateFormat format = new SimpleDateFormat( "hh:mm:ss" );
String nowStr = format.format(now);
try {
dataOutputStream.writeUTF("(^_^)∠※--->" + username
+ " : " + nowStr + " 说\n" + chat_txt);
} catch (IOException e2) {
}
} else {
try {
dataOutputStream.writeUTF("请发言!!!" );
} catch (IOException e3) {
}
}
break ;
case R.id.LeaveButton:
if (flag == true ) {
if (flag == false ) {
Toast.makeText(ChatClientActivity.this ,
"亲,你还没登录,请先登录!" , Toast.LENGTH_LONG).show();
return ;
}
try {
dataOutputStream.writeUTF("(^_^)/~~ " + username
+ "下线了!" );
dataOutputStream.close();
dataInputStream.close();
socket.close();
} catch (IOException e4) {
}
}
flag = false ;
Toast.makeText(ChatClientActivity.this , "已退出!" ,
Toast.LENGTH_LONG).show();
break ;
}
}
};
@Override
public void run() {
while ( true ) {
try {
chat_in = dataInputStream.readUTF();
chat_in = chat_in + "\n" ;
mHandler.sendMessage(mHandler.obtainMessage());
} catch (IOException e) {
}
}
}
Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
historyEdit.append(chat_in);
super .handleMessage(msg);
}
};
}
7,亲,别忘了由于需要网络,需要添加联网的权限哦!!
< uses-permission android:name = "android.permission.INTERNET" />
8.如果你完成以上功能,就可以实现android手机客户端上的简单的聊天功能了,运行结果给如下: