简易界面
Android客户端登录
Android客户端登录后服务器和PC客户端界面
Android客户端和PC客户端聊天
注:在同一台PC机下测试,故所有的IP都一样了。
相关原理
1 Socket传输模式
2 Socket构造
3 ServiceSocket构造
4 客户端Socket
5 输入输出流
6 关闭Socket和流
完整源码
1 服务器: tcpservice.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class tcpservice {
//服务器端口
private static final int SERVERPORT = 8080;
//存储所有客户端Socket连接对象
private static List<Socket> mClientList = new ArrayList<Socket>();
//线程池
private ExecutorService mExecutorService;
//ServerSocket对象
private ServerSocket mServerSocket;
//开启服务器
public static void main(String[] args) {
new tcpservice();
}
public tcpservice() {
try {
//设置服务器端口
mServerSocket = new ServerSocket(SERVERPORT);
//创建一个线程池
mExecutorService = Executors.newCachedThreadPool();
System.out.println("start...");
//用来临时保存客户端连接的Socket对象
Socket client = null;
while (true) {
//接收客户连接并添加到list中
client = mServerSocket.accept();
mClientList.add(client);
//开启一个客户端线程
mExecutorService.execute(new ThreadServer(client));
}
}
catch (IOException e) {
e.printStackTrace();
}
}
//每个客户端单独开启一个线程
static class ThreadServer implements Runnable {
private Socket mSocket;
private BufferedReader mBufferedReader;
private PrintWriter mPrintWriter;
private String mStrMSG;
public ThreadServer(Socket socket) throws IOException {
this.mSocket = socket;
mBufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
mStrMSG = "user:"+this.mSocket.getInetAddress()+" come total:" + mClientList.size();
sendMessage();
}
public void run() {
try {
while ((mStrMSG = mBufferedReader.readLine()) != null) {
if (mStrMSG.trim().equals("exit")) {
//当一个客户端退出时
mClientList.remove(mSocket);
mBufferedReader.close();
mPrintWriter.close();
mStrMSG = "user:"+this.mSocket.getInetAddress()+" exit total:" + mClientList.size();
mSocket.close();
sendMessage();
break;
}
else {
mStrMSG = mSocket.getInetAddress() + ":" + mStrMSG;
sendMessage();
}
}
}
catch (IOException e) {
e.printStackTrace();
}
}
//发送消息给所有客户端
private void sendMessage() throws IOException {
System.out.println(mStrMSG);
for (Socket client : mClientList) {
mPrintWriter = new PrintWriter(client.getOutputStream(), true);
mPrintWriter.println(mStrMSG);
}
}
}
}
2 Android客户端java :: tcpclient.java
package com.example.bjl.tcp;
import com.example.bjl.R;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class tcpclient extends Activity {
// 声明对象
private Button mInButton, mSendButton;
private EditText mEditText01, mEditText02;
private static final String SERVERIP = "192.168.31.233";
private static final int SERVERPORT = 8080;
private Thread mThread = null;
private Socket mSocket = null;
private BufferedReader mBufferedReader = null;
private PrintWriter mPrintWriter = null;
private static String mStrMSG = "";
private static String TAG = "TCP";
private MyHandler mHandler = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.tcpclient);
mInButton = (Button) findViewById(R.id.myinternet_tcpclient_BtnIn);
mSendButton = (Button) findViewById(R.id.myinternet_tcpclient_BtnSend);
mEditText01 = (EditText) findViewById(R.id.myinternet_tcpclient_EditText01);
mEditText02 = (EditText) findViewById(R.id.myinternet_tcpclient_EditText02);
mHandler = new MyHandler(mEditText01);
// 登陆
mInButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
try {
// ①Socket实例化,连接服务器
mSocket = new Socket(SERVERIP, SERVERPORT);
// ②获取Socket输入输出流进行读写操作
mBufferedReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
mPrintWriter = new PrintWriter(mSocket.getOutputStream(), true);
} catch (Exception e) {
// TODO: handle exception
Log.e(TAG, e.toString());
}
}
});
// 发送消息
mSendButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
try {
// 取得编辑框中我们输入的内容
String str = mEditText02.getText().toString() + "\n";
Log.e(TAG, str);
// 发送给服务器
mPrintWriter.print(str);
mPrintWriter.flush();
} catch (Exception e) {
// TODO: handle exception
Log.e(TAG, e.toString());
}
}
});
mThread = new Thread(mRunnable);
mThread.start();
}
// 线程:监听服务器发来的消息
private Runnable mRunnable = new Runnable() {
public void run() {
while (true) {
try {
if ((mStrMSG = mBufferedReader.readLine()) != null) {
mStrMSG += "\n";// 消息换行
mHandler.sendMessage(mHandler.obtainMessage());// 发送消息
}
} catch (Exception e) {
Log.e(TAG, e.toString());
}
}
}
};
/*
Handler mHandler = new Handler() { //更新界面的显示(不能直接在线程中更新视图,因为Android线程是安全的)
public void handleMessage(Message msg) {
super.handleMessage(msg);
// 刷新
try {
mEditText01.append(mStrMSG);// 将聊天记录添加进来
} catch (Exception e) {
Log.e(TAG, e.toString());
}
}
};
*/
static class MyHandler extends Handler { //更新界面的显示(不能直接在线程中更新视图,因为Android线程是安全的)
EditText tv;
MyHandler(EditText tv) {
this.tv = tv;
}
public void handleMessage(Message msg) {
super.handleMessage(msg);
this.tv.append(mStrMSG);// 将聊天记录添加进来
}
}
}
布局文件: tcpclient.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/myinternet_tcpclient_EditText01"
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="top"
android:text="聊天记录:\n" />
<EditText
android:id="@+id/myinternet_tcpclient_EditText02"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="输入要发送的内容" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center" >
<Button
android:id="@+id/myinternet_tcpclient_BtnIn"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="登陆" />
<Button
android:id="@+id/myinternet_tcpclient_BtnSend"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="发送" />
</LinearLayout>
</LinearLayout>
3 PC客户端: tcpclient2.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class tcpclient2 {
private static final int PORT = 8080;
private static ExecutorService exec = Executors.newCachedThreadPool();
public static void main(String[] args) throws Exception {
new tcpclient2();
}
public tcpclient2() {
try {
Socket socket = new Socket("192.168.31.233", PORT);
exec.execute(new Sender(socket));
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg;
while ((msg = br.readLine()) != null) {
System.out.println(msg);
}
} catch (Exception e) {
}
}
// 客户端线程获取控制台输入消息
static class Sender implements Runnable {
private Socket socket;
public Sender(Socket socket) {
this.socket = socket;
}
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
String msg;
while (true) {
msg = br.readLine();
pw.println(msg);
if (msg.trim().equals("exit")) {
pw.close();
br.close();
exec.shutdownNow();
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
转自: http://www.cnblogs.com/skyseraph/archive/2012/03/12/2391601.html