補充,因爲這篇文章是本身入門的時候寫的,隨着Android系統的升級可能有發送須要在任務html
中進行,若有問題請百度 threadjava
或者看下面連接的文章android
https://www.cnblogs.com/yangfengwu/category/1187355.html服務器
吸收教訓!!!原本花了5個小時寫完了,沒想到,,,由於沒點上面的自動保存查看一下,全沒了,從新寫唄網絡
關於網絡通訊:每一臺電腦都有本身的ip地址,每臺電腦上的網絡應用程序都有本身的通訊端口,張三的電腦(ip:192.168.1.110)上有一個網絡應用程序A(通訊端口5000),李四的電腦(ip:192.168.1.220)上有一個網絡應用程序B(通訊端口8000),張三給李四發消息,首先你要知道李四的ip地址,向指定的ip(李四ip:192.168.1.220)發信息,信息就發到了李四的電腦。再指定一下發送的端口號(通訊端口8000),信息就發到了李四電腦的網絡應用程序B上。app
TCP--一種網絡通訊方式而已。分爲服務器(網絡應用程序)和客戶端(網絡應用程序),TCP通訊過程,首先打開服務器,監聽本身的網絡通訊端口(假設爲9000),打開客戶端,設置好要鏈接的ip地址和服務器的網絡通訊端口(9000),這樣服務器一旦監聽到網絡通訊端口有鏈接,兩者就創建了鏈接。socket
好一步一步寫程序(最後有源碼!!!!!!!)ide
怎樣創建工程就不說了,原本寫好了並貼了圖,網絡一有問題全沒了。抱怨一下,博客傳圖片真麻煩。居然不支持複製 粘貼。各位朋友有什麼方便的方法請告知。函數
在佈局文件里加入兩個按鈕(button),一個控制鏈接,一個控制發送消息;四個輸入文本框(edittext),一個填寫發送的信息內容,一個顯示服務器發來的消息。一個填寫要連接的ip地址,一個填寫要連接的端口號佈局
佈局代碼
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.wifi123.MainActivity" >以上都不用管的,軟件自動生成的,配置界面的
<!--顯示的標題:目標IP地址-->
<TextView
android:textSize="20dp"字體大小
android:id="@+id/IP_tv" id號
android:text="目標IP地址" 顯示的內容
android:layout_width="wrap_content" 寬度隨內容而定
android:layout_height="wrap_content" 高度度隨內容而定
/>
<!--顯示的標題:目標端口號-->
<TextView
android:textSize="20dp"
android:id="@+id/Port_tv"
android:text="目標端口號"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/IP_tv" 在<!--顯示的標題:目標IP地址-->的下面
android:layout_marginTop="30dp" 離它上面那個組件(<!--顯示的標題:目標IP地址-->)的距離
/>
<!-- 用於填寫ip地址的文本框-->
<EditText
android:text="192.168.4.1"
android:id="@+id/ip_ET"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/IP_tv" 在<!--顯示的標題:目標IP地址-->的右面
/>
<!-- 用於填寫端口號的文本框-->
<EditText
android:text="8080"
android:id="@+id/Port_ET"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/Port_tv" 仍是在誰誰誰的右面
android:layout_alignBottom="@id/Port_tv" 本元素的下邊緣和某元素的的下邊緣對齊
/>
<!-- 用於發送信息的文本框-->
<EditText
android:id="@+id/Send_ET"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/Port_tv" 在某元素的下方
/>
<!-- 用於鏈接的按鈕-->
<Button
android:text="鏈接"
android:id="@+id/Connect_Bt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="Connect_onClick"設置按鈕的動做監聽函數,其實有幾種寫法,就用最簡單的一種
android:layout_below="@id/Send_ET" 在某元素的下方
/>
<!-- 用於發送信息的按鈕-->
<Button
android:text="發送"
android:id="@+id/Send_Bt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="Send_onClick"
android:layout_below="@id/Send_ET"
android:layout_alignParentRight="true" 貼緊父元素的右邊緣,指的是總體的界面
/>
<!-- 用於接收信息的文本框-->
<EditText
android:background="@android:color/darker_gray"
android:id="@+id/Receive_ET"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/Connect_Bt"
android:layout_alignParentBottom="true" 貼緊父元素的下邊緣
/>
</RelativeLayout>
看看佈局界面
接着開始編寫功能程序
先作點擊鏈接按鈕就鏈接服務器
查看java的API文檔,裏面封裝了專門用於TCP客戶端通訊的類,和方法
裏面有一個類Socket (客服端),有一個它的構造方法
Socket(InetAddress address, int port)
建立一個流套接字並將其鏈接到指定 IP 地址的指定端口號。
意思是Socket socket = new Socket(InetAddress address, int port) ;//建立鏈接地址和端口,就去鏈接指定的ip和端口號去了,address填ip地址,port填端口號
只不過InetAddress是一個類,咱們打開看一下
那麼
InetAddress ipAddress = InetAddress.getByName("192.168.4.1");
socket = new Socket(ipAddress, 8080);//建立鏈接地址和端口--------------就完了,客戶端就去鏈接了
可是ip地址和端口被咱們定死了,,,,可很差玩,咱們就設置成獲取ip文本框中的ip,端口號文本框中的端口號
InetAddress ipAddress = InetAddress.getByName(IPEditText.getText().toString());
int port =Integer.valueOf(PortText.getText().toString());//獲取端口號
socket = new Socket(ipAddress, port);//建立鏈接地址和端口-------------------這樣就好多了
可是因爲在android幾開始,不容許在主線程裏鏈接服務器,因此只好讓按鈕點擊後啓動一個線程裏面寫上面的東西
package com.wifi123;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
Button ConnectButton;//定義鏈接按鈕
Button SendButton;//定義發送按鈕
EditText IPEditText;//定義ip輸入框
EditText PortText;//定義端口輸入框
EditText MsgText;//定義信息輸出框
EditText RrceiveText;//定義信息輸入框
Socket socket = null;//定義socket
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ConnectButton = (Button) findViewById(R.id.Connect_Bt);//得到按鈕對象
SendButton = (Button) findViewById(R.id.Send_Bt);//得到按鈕對象
IPEditText = (EditText) findViewById(R.id.ip_ET);//得到ip文本框對象
PortText = (EditText) findViewById(R.id.Port_ET);//得到端口文本框按鈕對象
}
public void Connect_onClick(View v) {
//啓動鏈接線程
Connect_Thread connect_Thread = new Connect_Thread();
connect_Thread.start();
}
class Connect_Thread extends Thread//繼承Thread
{
public void run()//重寫run方法
{
try
{
if (socket == null) //若是已經鏈接上了,就再也不執行鏈接程序
{
//用InetAddress方法獲取ip地址
InetAddress ipAddress = InetAddress.getByName(IPEditText.getText().toString());
int port =Integer.valueOf(PortText.getText().toString());//獲取端口號
socket = new Socket(ipAddress, port);//建立鏈接地址和端口-------------------這樣就好多了
}
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
對了須要添加兩個權限,一個是wifi權限,一個是internet
而後下載到手機由於個人電腦的ip爲192.168.1.101,因此我把192.168.4.1改了,192.168.4.1是爲了作與wifi模塊EPS8266通訊使得
而後打開網絡調試助手,點擊鏈接(能夠關閉電腦防火牆),而後點擊手機上的鏈接
好接着,鏈接按鈕按一下鏈接,再按一下斷開鏈接,而且,鏈接後按鈕上顯示斷開,斷開後按鈕上顯示鏈接
按鈕事件改成
public void Connect_onClick(View v) {
if (isConnect == true) //標誌位 = true表示鏈接
{
isConnect = false;//置爲false
ConnectButton.setText("斷開");//按鈕上顯示--斷開
//啓動鏈接線程
Connect_Thread connect_Thread = new Connect_Thread();
connect_Thread.start();
}
else //標誌位 = false表示退出鏈接
{
isConnect = true;//置爲true
ConnectButton.setText("鏈接");//按鈕上顯示鏈接
try
{
socket.close();//關閉鏈接
socket=null;
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
你能夠試一試了
接着寫點擊發送按鈕把發送信息文本框的內容發送出去
先貼代碼
public void Send_onClick(View v) {
try
{
//獲取輸出流
outputStream = socket.getOutputStream();
//發送數據
outputStream.write(MsgEditText.getText().toString().getBytes());
//outputStream.write("0".getBytes());
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
看看javaAPI
因此纔有了
//獲取輸出流
OutputStream outputStream = socket.getOutputStream();
//發送數據
outputStream.write(MsgEditText.getText().toString().getBytes());
接收數據並在信息框顯示出來
建立一個接收線程,在鏈接線程成功創建鏈接後啓動接收線程
//接收線程
class Receive_Thread extends Thread
{
public void run()//重寫run方法
{
try
{
while (true)
{
final byte[] buffer = new byte[1024];//建立接收緩衝區
inputStream = socket.getInputStream();
final int len = inputStream.read(buffer);//數據讀出來,而且返回數據的長度
runOnUiThread(new Runnable()//不容許其餘線程直接操做組件,用提供的此方法能夠
{
public void run()
{
// TODO Auto-generated method stub
RrceiveEditText.setText(new String(buffer,0,len));
}
});
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//鏈接線程
class Connect_Thread extends Thread//繼承Thread
{
public void run()//重寫run方法
{
try
{
if (socket == null)
{
//用InetAddress方法獲取ip地址
InetAddress ipAddress = InetAddress.getByName(IPEditText.getText().toString());
int port =Integer.valueOf(PortText.getText().toString());//獲取端口號
socket = new Socket(ipAddress, port);//建立鏈接地址和端口-------------------這樣就好多了
//在建立完鏈接後啓動接收線程
Receive_Thread receive_Thread = new Receive_Thread();
receive_Thread.start();
}
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
下面貼所有源碼
activity_mian.xml源碼
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.wifi123.MainActivity" >
<!--顯示的標題:目標IP地址-->
<TextView
android:textSize="20dp"
android:id="@+id/IP_tv"
android:text="目標IP地址"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<!--顯示的標題:目標端口號-->
<TextView
android:textSize="20dp"
android:id="@+id/Port_tv"
android:text="目標端口號"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/IP_tv"
android:layout_marginTop="30dp"
/>
<!-- 用於填寫ip地址的文本框-->
<EditText
android:text="192.168.1.101"
android:id="@+id/ip_ET"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/IP_tv"
/>
<!-- 用於填寫端口號的文本框-->
<EditText
android:text="8080"
android:id="@+id/Port_ET"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/Port_tv"
android:layout_alignBottom="@id/Port_tv"
/>
<!-- 用於發送信息的文本框-->
<EditText
android:id="@+id/Send_ET"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/Port_tv"
/>
<!-- 用於鏈接的按鈕-->
<Button
android:text="鏈接"
android:id="@+id/Connect_Bt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="Connect_onClick"
android:layout_below="@id/Send_ET"
/>
<!-- 用於發送信息的按鈕-->
<Button
android:text="發送"
android:id="@+id/Send_Bt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="Send_onClick"
android:layout_below="@id/Send_ET"
android:layout_alignParentRight="true"
/>
<!-- 用於接收信息的文本框-->
<EditText
android:background="@android:color/darker_gray"
android:id="@+id/Receive_ET"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/Connect_Bt"
android:layout_alignParentBottom="true"
/>
</RelativeLayout>
MainActivity.java源碼
package com.wifi123;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
boolean isConnect=true;//鏈接仍是斷開 Button ConnectButton;//定義鏈接按鈕 Button SendButton;//定義發送按鈕 EditText IPEditText;//定義ip輸入框 EditText PortText;//定義端口輸入框 EditText MsgEditText;//定義信息輸出框 EditText RrceiveEditText;//定義信息輸入框 Socket socket = null;//定義socket private OutputStream outputStream=null;//定義輸出流 private InputStream inputStream=null;//定義輸入流 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ConnectButton = (Button) findViewById(R.id.Connect_Bt);//得到鏈接按鈕對象 SendButton = (Button) findViewById(R.id.Send_Bt);//得到發送按鈕對象 IPEditText = (EditText) findViewById(R.id.ip_ET);//得到ip文本框對象 PortText = (EditText) findViewById(R.id.Port_ET);//得到端口文本框按鈕對象 MsgEditText = (EditText) findViewById(R.id.Send_ET);//得到發送消息文本框對象 RrceiveEditText = (EditText) findViewById(R.id.Receive_ET);//得到接收消息文本框對象 } public void Connect_onClick(View v) { if (isConnect == true) //標誌位 = true表示鏈接 { isConnect = false;//置爲false ConnectButton.setText("斷開");//按鈕上顯示--斷開 //啓動鏈接線程 Connect_Thread connect_Thread = new Connect_Thread(); connect_Thread.start(); } else //標誌位 = false表示退出鏈接 { isConnect = true;//置爲true ConnectButton.setText("鏈接");//按鈕上顯示鏈接 try { socket.close();//關閉鏈接 socket=null; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void Send_onClick(View v) { try { //獲取輸出流 outputStream = socket.getOutputStream(); //發送數據 outputStream.write(MsgEditText.getText().toString().getBytes()); //outputStream.write("0".getBytes()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } //鏈接線程 class Connect_Thread extends Thread//繼承Thread { public void run()//重寫run方法 { try { if (socket == null) { //用InetAddress方法獲取ip地址 InetAddress ipAddress = InetAddress.getByName(IPEditText.getText().toString()); int port =Integer.valueOf(PortText.getText().toString());//獲取端口號 socket = new Socket(ipAddress, port);//建立鏈接地址和端口-------------------這樣就好多了 //在建立完鏈接後啓動接收線程 Receive_Thread receive_Thread = new Receive_Thread(); receive_Thread.start(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //接收線程 class Receive_Thread extends Thread { public void run()//重寫run方法 { try { while (true) { final byte[] buffer = new byte[1024];//建立接收緩衝區 inputStream = socket.getInputStream(); final int len = inputStream.read(buffer);//數據讀出來,而且返回數據的長度 runOnUiThread(new Runnable()//不容許其餘線程直接操做組件,用提供的此方法能夠 { public void run() { // TODO Auto-generated method stub RrceiveEditText.setText(new String(buffer,0,len)); } }); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }}