其实是个很简单的事情,服务端(PC)用一个端口新建一个socket然后等待客户端设备过来连接,而客户端(Android)只需用服务端IP和服务端端口去创建socket连接就行。
可是问题是我花了两小时一直就没连上…….刚刚觉得可能是IP地址的问题,尝试了使用120.0.0.1(回环地址),尝试了10.0.2.2(模拟机和电脑互联的地址),192.168.1.27(PC的无线网卡IP)结果都连不上。后来百度无果,问了一位大神,一语道破,原来是PC的防火墙打开了,导致局域网其他设备无法通过socket连接到PC。
下面板书下完整的代码,包括客户端(Android程序)和服务端(java程序),ps:是某博客摘抄的,然后后面会有自己的理解。
客户端
package com.example.socketclient;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
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 {
EditText input;
TextView show;
Button send;
Handler handler;
ClientThread clientThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
input = (EditText) findViewById(R.id.input);
show = (TextView) findViewById(R.id.show);
send = (Button) findViewById(R.id.send);
handler =
new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what ==
0x123) {
show.append(
"\n" + msg.obj.toString());
}
}
};
clientThread =
new ClientThread(handler);
new Thread(clientThread).start();
send.setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
try {
Message msg =
new Message();
msg.what =
0x345;
msg.obj = input.getText().toString();
clientThread.revHandler.sendMessage(msg);
input.setText(
"");
}
catch (Exception e) {
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
package com.example.socketclient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
public class ClientThread implements Runnable {
private Socket s;
Handler handler;
Handler revHandler;
BufferedReader br =
null;
OutputStream os =
null;
public ClientThread(Handler handler) {
this.handler = handler;
}
@Override
public void run() {
s =
new Socket();
try {
s.connect(
new InetSocketAddress(
"192.168.1.27",
51706),
5000);
br =
new BufferedReader(
new InputStreamReader(s.getInputStream()));
os = s.getOutputStream();
new Thread() {
@Override
public void run() {
String content =
null;
try {
while ((content = br.readLine()) !=
null) {
Message msg =
new Message();
msg.what =
0x123;
msg.obj = content;
handler.sendMessage(msg);
}
}
catch (IOException io) {
io.printStackTrace();
}
}
}.start();
Looper.prepare();
revHandler =
new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what ==
0x345) {
try {
os.write((msg.obj.toString() +
"\r\n").getBytes(
"gbk"));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
};
Looper.loop();
}
catch (SocketTimeoutException e) {
Message msg =
new Message();
msg.what =
0x123;
msg.obj =
"网络连接超时!";
handler.sendMessage(msg);
}
catch (IOException io) {
io.printStackTrace();
}
}
}
<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=
".MainActivity" >
<EditText
android:id=
"@+id/input"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:hint=
"input" />
<Button
android:id=
"@+id/send"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:text=
"send"
android:layout_below=
"@id/input"/>
<TextView
android:id=
"@+id/show"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_below=
"@id/send"/>
<
/RelativeLayout>
服务端
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class MyService {
public static List<Socket> socketList =
new ArrayList<Socket>();
public static void main(String[] args)
throws IOException {
ServerSocket server =
new ServerSocket(
51706);
while(
true){
System.out.println(
"in connecting");
Socket s=server.accept();
socketList.add(s);
new Thread(
new ServiceThread(s)).start();
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class ServiceThread implements Runnable {
Socket s =
null;
BufferedReader br =
null;
public ServiceThread(Socket s) {
this.s = s;
try {
br =
new BufferedReader(
new InputStreamReader(s.getInputStream()));
}
catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
String content =
null;
while((content=readFromClient())!=
null){
for(Socket s:MyService.socketList){
OutputStream os;
try {
os = s.getOutputStream();
os.write((content+
"\n").getBytes(
"gbk"));
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
public String
readFromClient() {
try {
return br.readLine();
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
一些理解
服务端先监听到来的客户端连接,来一个客户端,就开启一个线程为它服务。服务过程:客户端发一串字符到服务端,然后服务端再返回同样的字符。整个过程相比c语言socket编程的代码复杂度上简单很多,socket编程中传输的其实是字节流,从读写函数就可以看到,写入的是byte数组,那么客户端和服务端必须规定使用同样的字符集编解码,才能做到不出现乱码。就是说客户端的对二进制流的编码和服务端对二进制流的解码的字符集要一致,例子中采用的都是gbk。
转载请注明原文地址: https://ju.6miu.com/read-662329.html