TCP 是什麼,可能有些人不知道先掃一下盲吧。
TCP:Transmission Control Protocol 傳輸控制通訊協定。TCP是一種連線導向(串連導向)的、可靠的、基於位元組流的運輸層(Transport layer)通訊協定。
相當於一個聊天的小應用程式,只能發送文字。
Server端是一個java project 僅僅有一個類Server 代碼如下:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Server {
boolean started=false;
ServerSocket ss=null;
Socket s=null;
DataInputStream dis=null;
List<Client> clients=new ArrayList<Client>();
public void start(){
try {
//ServerSocket一直監聽TCP的8888連接埠,1024以內的連接埠為系統所用
ss=new ServerSocket(8888);
started=true;
}catch(BindException e){
System.out.println("連接埠使用中......");
System.out.println("請關掉相關 程式,重新運行伺服器");
System.exit(0);
}
catch(IOException e){
e.printStackTrace();
}
try {
while(started){
/ServerSocket一直監聽,一旦/有用戶端串連上來就增加一個Client,來記錄這個串連。
s=ss.accept();
Client c=new Client(s);
new Thread(c).start();
//dis.close();
clients.add(c);
}
} catch (Exception e) {
// TODO Auto-generated catch block
try {
dis.close();
s.close();
}
catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
finally{
try {
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Server().start();
}
class Client implements Runnable{
private Socket s=null;
private DataInputStream dis=null;
private DataOutputStream dos=null;
private boolean bconnected=false;
Client(Socket s){
this.s=s;
try {
dis=new DataInputStream(s.getInputStream());
dos=new DataOutputStream(s.getOutputStream());
bconnected=true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void send(String s){
try {
dos.writeUTF(s);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
try {
while (bconnected) {
String str = dis.readUTF();
//如果有一個用戶端發送字串,伺服器就把這個字串發送給其他用戶端(除了它自己之外)
for(int i=0;i<clients.size();i++){
Client c=clients.get(i);
if(c!=this)
c.send(str+"\n");
}
}
} catch (EOFException e2) {
System.out.println("Client closed!");
} catch (Exception e) {
// TODO Auto-generated catch block
try {
dis.close();
s.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} finally {
try {
if (dis != null)
dis.close();
if(dos!=null)
dos.close();
if (s != null)
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
Android 用戶端就一個Activity,他的代碼如下:
package com.broadvision.chat;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView displayArea;
private EditText sendArea;
private Button sendButton;
Socket s=null;
DataOutputStream dao=null;
DataInputStream dis=null;
private boolean bconnect=false;
public void connect(){
try {
//Socket 的Ip地址應該用PC的區域網路的IP,不能用127.0.0.1代替,否則Android用戶端不能串連到Server上
s=new Socket("192.168.1.100",8888);
dao=new DataOutputStream(s.getOutputStream());
dis=new DataInputStream(s.getInputStream());
System.out.println("Connected!");
bconnect=true;
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
public void disconnect(){
try {
dao.close();
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private class Read implements Runnable{
public void run() {
try {
while(bconnect){
final String s=dis.readUTF();
System.out.println("read utf=====" + s);
runOnUiThread(new Runnable() {
@Override
public void run() {
displayArea.append(s);
}
});
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
displayArea = (TextView) findViewById(R.id.display_area);
sendArea = (EditText) findViewById(R.id.send_area);
sendButton = (Button) findViewById(R.id.send_button);
connect();
new Thread(new Read()).start();
//當點解“Send”Button時候,就向伺服器發送字串。
sendButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String str=sendArea.getText().toString().trim();
displayArea.append(str+"\n");
sendArea.setText("");
try {
dao.writeUTF(str);
dao.flush();
//dao.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
}
}
Activity的layout檔案內容如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:id="@+id/display_area"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="3"
/>
<EditText
android:id="@+id/send_area"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="Send some message" />
<Button android:id="@+id/send_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="Send" />
</LinearLayout>
Android項目中的Manifest xml 中應該增加 <uses-permission android:name="android.permission.INTERNET"/> 許可權。
Android 項目安裝到模擬器和手機上面,
模擬器的如下:
手機的如下:
希望能對大家有所協助,謝謝指正其中的錯誤。