炒沙作縻终不饱,缕冰文章费工巧。这篇文章主要讲述Android客户端与本地服务器Socket通信相关的知识,希望能为你提供帮助。
android客户端与本地服务器Socket通信
Socket服务器运行结果图??
文章图片
一.客户端和服务器端的选择:
- 客户端是我们手机端,关于服务器端,只要安装了JDK,自然就拥有通讯的功能,我们只需要在Eclipse或者MyEclipse中写好文章中服务器端的代码,运行起来即可,用accept()方法启动服务器端,等待客户端的连接,在未连接的情况下,服务器端处于堵塞的状态。
- andriod客户端添加网络访问权限
< uses-permission android:name="android.permission.INTERNET" />
- 对Socket的操作放在非UI线程内进行
- 要使用正确的IP地址和端口号端口号的范围是0~65535,1024一下的端口被系统分给了一些服务,在cmd窗口执行
netstat -ano
命令可以看到所有端口的使用情况
- 真机进行调试(1、连接上手机,手机开启adb。步骤:设置>
应用程序>
开发>
选择USB调试;
usb选项有些不可见,具体百度),指定Server的IP地址,此地址为局域网地址,如果是使用WIFI上网,则为PC机的WIFI IP。上图中连接的第二个就是示例。
三.Socket通信 - 利用ip地址+端口号唯一标示网络中的一个进程,能够唯一标示网络中的进程后,它们就可以利用socket进行通信。
- socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用,实现进程在网络中通信。
- socket是"打开—读/写—关闭"模式的实现(只能读取对方放在流中的数据),以使用TCP协议通讯的socket为例,其交互流程大概是这样子的
- Socket有两种主要的操作方式:面向连接的和无连接的,即TCP和UDP。
面向连接的Socket操作就像一部电话,Socket必须在发送数据之前与目的地的Socket取得连接,一旦连接建立了,Socket就可以使用一个流接口进行打开、读写以及关闭操作。并且,所有发送的数据在另一端都会以相同的顺序被接收。
- 无连接的Socket操作就像一个邮件投递,每一个数据报都是一个独立的单元,它包含了这次投递的所有信息(目的地址和要发送的内容)。在这个模式下的Socket不需要连接目的地Socket,它只是简单的投出数据报。
四.TCP连接与HTTP连接与Socket连接的区别 - TCP连接与HTTP连接的区别
- TCP连接与Socket连接的区别:
- HTTP连接与Socket连接的区别
HTTP连接服务端无法主动发消息。决定二者分别适合应用在什么场景下。HTTP采用“请求-响应”机制,必须满足客户端发送消息在前,服务端回复在后。Socket连接双方类似peer2peer的关系,一方随时可以向另一方喊话。
- 什么时候该用HTTP,什么时候该用socket
用Socket的情况:大部分即时通讯应用(QQ、微信)、聊天室、苹果APNs等。
五.socket代码客户端代码
public class MainActivity extends AppCompatActivity {
//IP地址和端口号
public static String IP_ADDRESS = "192.168.1.106";
public static int PORT = 2346;
//三个控件
EditText text = null;
Button connect = null;
TextView info = null;
//handler
Handler handler = null;
Socket soc = null;
DataOutputStream dos = null;
DataInputStream dis = null;
String messageRecv = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (EditText) findViewById(R.id.editText);
connect = (Button) findViewById(R.id.buttonConnection);
info = (TextView) findViewById(R.id.info);
connect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new ConnectionThread(text.getText().toString()).start();
}
});
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Bundle b = msg.getData();
//获取消息中的Bundle对象
String str = b.getString("data");
//获取键为data的字符串的值
info.append(str);
}
};
}//新建一个子线程,实现socket通信
class ConnectionThread extends Thread {
String message = null;
public ConnectionThread(String msg) {
message = msg;
}@Override
public void run() {
if (soc == null) {
try {
//Log.d("socket","new socket");
soc = new Socket(IP_ADDRESS, PORT);
//获取socket的输入输出流
dis = new DataInputStream(soc.getInputStream());
dos = new DataOutputStream(soc.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
dos.writeUTF(message);
dos.flush();
messageRecv = dis.readUTF();
//如果没有收到数据,会阻塞
Message msg = new Message();
Bundle b = new Bundle();
b.putString("data", messageRecv);
msg.setData(b);
handler.sendMessage(msg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
`
服务器端代码
public class Server {ServerSocket serverSocket = null;
public final int port = 2346;
public Server(){//输出服务器的IP地址
try {
InetAddress addr = InetAddress.getLocalHost();
System.out.println("local host:"+addr);
serverSocket = new ServerSocket(port);
System.out.println("0k");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}public void startService(){try {
Socket socket = null;
System.out.println("waiting...");
//等待连接,每建立一个连接,就新建一个线程
while(true){
socket = serverSocket.accept();
//等待一个客户端的连接,在连接之前,此方法是阻塞的
System.out.println("connect to"+socket.getInetAddress()+":"+socket.getLocalPort());
new ConnectThread(socket).start();
}} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("IOException");
e.printStackTrace();
}
}//向客户端发送信息
class ConnectThread extends Thread{
Socket socket = null;
public ConnectThread(Socket socket){
super();
this.socket = socket;
}@Override
public void run(){
try {
DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
while(true){
String msgRecv = dis.readUTF();
System.out.println("msg from client:"+msgRecv);
dos.writeUTF("received:"+msgRecv);
dos.flush();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new Server().startService();
}}
代码的逻辑客户端 :
- 【Android客户端与本地服务器Socket通信】初始化控件,并绑定监听器,编写按钮的事件处理代码。
- 在事件处理代码中开启子线程,子线程中通过Sockt访问服务器。
- 利用异步消息处理机制,message对象将子线程的数据传回handle的处理方法更新UI。
- serversocket对象监听等待,利用循环当有客户访问就开启子线程处理传消息回客户端。(模拟器和手机同时通过局域网访问)
最后的废话
- 搞计算机必须得有理论指导实践,否则只能像个没头苍蝇到处乱撞,我的计算机网络知识真的是一言难尽。
- 各大语言的官网是个好东西。丰富的资料和教程简直让人沉醉其中不能自拔。虽然比不上网络小说通俗易懂,但是引人入胜一点也不差。
- 不会的东西太多,用谷歌插件等工具列表,先解决主要的,平时有想法也可以记录。
- 用博客整理自己的知识,形成体系。看得再多不如编一遍。
2018-05-13 22:15:53 星期日
推荐阅读
- Could not get unknown property 'packageForR' for task ':app:processDebugReso
- Android MediaRecorder录制视频提示start failed的解决办法
- [Android] TextView 属性说明
- android studio bug : aidl is missing 解决方案
- 再杀掉app之后 删除NSUserDefault存在本地的数据
- Phalcon查询语言(PHQL)
- 环境部署(Phalcon安装详细步骤)
- Phalcon安全哈希
- Phalcon模型事务