(1)android客户端代码:
public class MainActivity extends Activity {
private EditText editText;
private Button button;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText)findViewById(R.id.editText1);
button = (Button)findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Thread thread=new Thread(new SendTask());//开启子线程是因为socket通信操作在Android某个版本后就不允许在主线程中进行了
thread.start();
}
});
}
class SendTask implements Runnable{
@Override
public void run() {
String str=editText.getText().toString();
Socket socket=null;
if(str.equals("")||str==null){
return;
}else{
try{
Log.d("Tankai","Thread="+Thread.currentThread().getName());
socket=new Socket("192.168.0.103",18895);//在此处将10.0.2.2作为电脑的IP地址行不通
DataOutputStream out=new DataOutputStream(socket.getOutputStream());
Log.d("Tankai","out="+out.toString()+" socket="+socket.toString());
out.writeUTF(str);
out.flush();
out.close();
}catch (IOException e){
Log.d("Tankai","无法获取IP:"+e.getMessage());
}finally {
if(null!=socket){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
}
(2)UI布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="hello" />
<EditText android:layout_width="match_parent" android:id="@+id/editText1"
android:layout_height="wrap_content"
android:hint="input the message and click the send button"
></EditText>
<Button android:text="send" android:id="@+id/button1"
android:layout_width="fill_parent" android:layout_height="wrap_content"></Button>
</LinearLayout>
(3)PC服务端代码:
public class Server {
//启动服务器
public static void main(String[] args){
Accept accept=new Accept();
Thread thread=new Thread(accept);
thread.start();
}
}
class Accept implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
Socket socket=null;
try {
ServerSocket serverSocket=new ServerSocket(18895);
while(true) {
System.out.println("start.......");
socket=serverSocket.accept();
System.out.println("socket="+socket.toString());
DataInputStream inputStream=new DataInputStream(socket.getInputStream());
String get=inputStream.readUTF();
System.out.println("手机-》电脑:"+get);
inputStream.close();
}
}catch (IOException e) {
// TODO: handle exception
System.out.println("fatal reason= "+e.getMessage());
}finally {
if(socket!=null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
(4)不要忘记加网络权限
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
(5)结果:
start.......
socket=Socket[addr=/192.168.0.100,port=60320,localport=18895]
手机-》电脑:145
start.......
socket=Socket[addr=/192.168.0.100,port=51000,localport=18895]
手机-》电脑:145258
start.......
分析说明:
(1)同样的一段代码,我用华为手机调试,结果却不能向电脑发送消息。显示错误是timeout,我用oppo手机却发送成功。可能是华为手机对socket进行了某些限制。
(2)每发送一次消息之后,再发送下一次消息,手机端的发送端口是改变了的,客户端的接收端口是写死的,没有改变。感觉这样每发一次消息,发送端口就改变,太浪费了。后面研究研究有没有优化方案。
(3)根据结果说明,每个设备在联网时都有一个ip地址,这个IP地址是会发生变化的。然后一个设备上有很多个端口,可以作为接收消息和发送消息的接口。
可以将一个设备理解为一个有很多大门的建筑物,它的地址就是ip(尽管这个IP是变化的),每一个大门就是一个端口,通过端口可以将物资运输进来或者发送出去。
(4)如果用上面的代码不能发送消息,可能的原因是电脑的防火墙限制了socket,尝试关闭一下。
(5)对socket的操作,要放在子线程下进行,目前Android版本是不支持将socket操作放在主线程下进行的。