Android客户端与本地服务器Socket通信
Posted workerbo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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连接的区别
HTTP是基于TCP的,客户端往服务端发送一个HTTP请求时第一步就是要建立与服务端的TCP连接。
- TCP连接与Socket连接的区别:
socket层只是在TCP/UDP传输层上做的一个抽象接口层,基于TCP协议的socket连接同样需要通过三次握手建立连接,是可靠的;基于UDP协议的socket连接不需要建立连接的过程,不过对方能不能收到都会发送过去,是不可靠的,大多数的即时通讯IM都是后者。
- HTTP连接与Socket连接的区别
HTTP是短连接,Socket(基于TCP协议的)是长连接。尽管HTTP1.1开始支持持久连接,但仍无法保证始终连接。而Socket连接一旦建立TCP三次握手,除非一方主动断开,否则连接状态一直保持。
HTTP连接服务端无法主动发消息。决定二者分别适合应用在什么场景下。HTTP采用“请求-响应”机制,必须满足客户端发送消息在前,服务端回复在后。Socket连接双方类似peer2peer的关系,一方随时可以向另一方喊话。
- 什么时候该用HTTP,什么时候该用socket
用HTTP的情况:双方不需要时刻保持连接在线,比如客户端资源的获取、文件上传等。
用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();
}
}
代码的逻辑
客户端 :
初始化控件,并绑定监听器,编写按钮的事件处理代码。
- 在事件处理代码中开启子线程,子线程中通过Sockt访问服务器。
利用异步消息处理机制,message对象将子线程的数据传回handle的处理方法更新UI。
服务端
- serversocket对象监听等待,利用循环当有客户访问就开启子线程处理传消息回客户端。(模拟器和手机同时通过局域网访问)
最后的废话
搞计算机必须得有理论指导实践,否则只能像个没头苍蝇到处乱撞,我的计算机网络知识真的是一言难尽。
- 各大语言的官网是个好东西。丰富的资料和教程简直让人沉醉其中不能自拔。虽然比不上网络小说通俗易懂,但是引人入胜一点也不差。
不会的东西太多,用谷歌插件等工具列表,先解决主要的,平时有想法也可以记录。
用博客整理自己的知识,形成体系。看得再多不如编一遍。
PS. 集成了很多地方的知识点,官网,博主,就不一一记录原地址了。
2018-05-13 22:15:53 星期日
以上是关于Android客户端与本地服务器Socket通信的主要内容,如果未能解决你的问题,请参考以下文章
在电子应用程序中实现socket.io,它与本地Web服务器通信