使用Java本身提供的
ServerSocket和Socket來進行連線的動作
且ServerSocket的接受連線方法accept()會讓程式停頓(直到成功連線為止),所以必須使用Thread
分為Server和Client兩部分的程式碼,在此我將其放在同個Project內...
Package內New → Class,命名為ServerCode,來撰寫伺服器端的程式碼。不過由於連線部分需要使用Thread,所以在另外新增一個Class,命名為ServerThreadCode
以及一個Class命名為ClientCode,來撰寫客戶端的程式碼。一樣需要使用到Thread,所以另外新增一個Class,命名為ClientThreadCode
ServerCode程式碼
public class ServerCode
{
public static void main(String[] argv)
{
new ServerThreadCode(8000).start();//建立物件,傳入Port並執行等待接受連線的動作
}
}
ServerThreadCode程式碼
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ServerThreadCode extends Thread
{
private ServerSocket m_serverSocket;//伺服器端的Socket,接收Client端的連線
private Socket m_socket;//Server和Client之間的連線通道
public ServerThreadCode(int port)
{
try
{
m_serverSocket = new ServerSocket(port);//建立伺服器端的Socket,並且設定Port
}
catch (IOException e)
{
System.out.println(e.getMessage());//出現例外時,捕捉並顯示例外訊息
}
}
@Override
public void run()//覆寫Thread內的run()方法
{
try
{
System.out.println("等待連線......");
m_socket = m_serverSocket.accept();//等待伺服器端的連線,若未連線則程式一直停在這裡
System.out.println("連線成功!");
m_serverSocket.close();//一旦連線建立成功,且不需要再接收其他連線,則可關閉ServerSocket
//送出端的編寫必須和接收端的接收Class相同
//使用Socket的getInputStream()和getOutputStream()進行接收和發送資料
//想要寫入字串可以用 PrintStream;想要把各種基本資料型態,如 int, double...等的 "值" 輸出,可以用 DataOutputStream;想要把整個物件 Serialize,則可以用 ObjectOutputStream。
PrintStream writer;//在此我使用PrintStream將字串進行編寫和送出
BufferedReader reader;//在此我使用BufferedReader將資料進行接收和讀取
writer = new PrintStream(m_socket.getOutputStream());//由於是將資料編寫並送出,所以是Output
//BufferedReader在建構時接受一個Reader物件,在讀取標準輸入串流時,會使用InputStreamReader,它繼承了Reader類別
reader = new BufferedReader(new InputStreamReader(m_socket.getInputStream()));//接收傳進來的資料,所以是Input
System.out.println("Client: " + reader.readLine());//讀取一行字串資料
SimpleDateFormat sdFormat = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");//設定時間格式
String nowDate = sdFormat.format(new Date());//取得現在時間
writer.println("現在時間是:" + nowDate);//將資料編寫進串流內
writer.flush();//清空緩衝區並送出資料
m_socket.close();//關閉連線
}
catch (IOException e)
{
System.out.println(e.getMessage());//出現例外時,捕捉並顯示例外訊息(連線成功不會出現例外)
}
}
}
再來是ClientCode程式碼
public class ClientCode
{
public static void main(String[] argv)
{
new ClientThreadCode("127.0.0.1", 8000).start();//建立物件,傳入IP和Port並執行等待接受連線的動作
//由於此範例都在自己電腦上執行,所以IP設定為127.0.0.1
}
}
ClientThreadCode程式碼(和Server端雷同,所以註解寫得不多)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
public class ClientThreadCode extends Thread
{
private Socket m_socket;//和伺服器端進行連線
public ClientThreadCode(String ip, int port)
{
try
{
m_socket = new Socket(ip, port);//建立連線。(ip為伺服器端的ip,port為伺服器端開啟的port)
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
}
@Override
public void run()
{
try
{
if (m_socket != null)//連線成功才繼續往下執行
{
//由於Server端使用 PrintStream 和 BufferedReader 來接收和寄送訊息,所以Client端也要相同
PrintStream writer = new PrintStream(m_socket.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(m_socket.getInputStream()));
writer.println("現在時間是?");
writer.flush();
System.out.println("Server:" + reader.readLine());
m_socket.close();
}
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
}
}
執行後的結果...(Server端)
只有Server執行(未連線)
當Client也執行時(已連線)
執行後的結果...(Client端)
(已連線)

你好 想問一下 如果外人要連server 要輸入甚麼ip?
假設A連接到B,那就要從A輸入B的IP(請輸入B的外部IP,若是輸入區網IP則搜尋不到)
版主您好,想請教您一個問題 我是在android studio上開發有關socket的App 但現在遇到一個問題是 我在主頁上連線成功 但跳到其他頁面後又要傳值 但系統告訴我connection reset 導致我後來跳頁前都要先關閉連線 到新的頁面後再重新連接 不知道版主有沒有遇過這樣的問題 該怎麼解決呢 感謝~
將該socket物件宣告為public static,讓所有activity共用這個物件 或者是將socket傳遞到新的activity
感謝版主大大 用static宣告後成功了 一直以為要讓第二個activity繼承第一個 感謝您~ 但也想順便請教一下 第二個方法傳遞socket 事利用什麼方法傳遞 Intent嗎?
是的 作法可參考這篇 http://style77125tech.pixnet.net/blog/post/16330639-%5Bandroid%5D-%E4%B8%8D%E5%90%8Cactivity%E4%B9%8B%E9%96%93%E7%9A%84%E8%B3%87%E6%96%99%E5%82%B3%E9%81%9E-%28bundle%29-
感謝 不過後來在執行時有遇到小問題 上面的是測試的專案 用static有成功 後來套用在主要的專案裡 卻發現都要extends有宣告static的那個class才能取得socket 這算是正常的嗎? 另外我之前學intent也是參考那篇的哈哈 但只有看到intent有put string int ....等等 卻沒看到適合傳socket的 方便請教傳socket該使用什麼呢? 抱歉借這再請教您一個問題 android studio有辦法在activity中控制layout屬性嗎 像是我按了個按鈕後 toolbar的background color改變這樣 謝謝解惑
使用putExtra把socket物件傳給另個activity 可以,只要你的layout有繼承View物件就行 例如:button1.setBackgroundColor(Color.RED);
還有一個忘了請教哈哈 不知道版主對onDestroy()有沒有研究 我在從activity跳回主頁時 想要onDestroy之前的activity以釋放資源 我是寫在toolbar的返回鍵裡 原本是寫finish() 後來改成onDestroy()但App會直接當掉不會跳回主頁 再後來改成 finsh() onDestroy() 這次就直接crash掉 想請問版主知道該如何正確使用onDestroy嗎 感謝
由於你的activity是由intent去開啟的 只要你的intnet物件生命周期結束就會自動釋放掉activity了 https://developer.android.com/guide/components/activities.html