Android使用Socket通信
在学习Socket之前,我们需要掌握一些知识,如java多线程等.代码上传至githug中Java多线程Java多线程了解Android客户端截图一些问题:DataInputStream reader;reader = new DataInputStream(mysocket.getInputStream());...
在学习Socket之前,我们需要掌握一些知识,如java多线程,Handler等.
Java多线程
https://blog.csdn.net/qq_40318498/article/details/84726026
C#Socket通信
https://blog.csdn.net/qq_40318498/article/details/90384688
Android Handler消息处理
https://blog.csdn.net/qq_40318498/article/details/89897690
源码已上传到github上
https://github.com/Githubforusc2018/AndroidSocket
使用技术
1.Handler
2.多线程
3.网络编程
Android登录界面截图
Android客户端界面截图
Android服务端界面截图
Client客户端核心代码
//连接服务器,返回的是一个Socket对象的连接来保持与服务器的通信.
int port = Integer.parseInt(clientPort.getText().toString());
mysocket = new Socket(clientIp.getText().toString(),port); //连成功了,服务器一直显示数据.
//一个子线程,循环读取消息.
while(true){
InputStream is = mysocket.getInputStream(); //192.168.43.224手机的wifi ip 地址.
byte[] buffer = new byte[1024*1024];
int len = is.read(buffer); //获取输入流,读取从服务端发送过来的消息.
String result = new String(buffer, 0, len);
/* 第一次读到的是Ip地址,必须保存.*/
if (mycount++==1){
myIp = result; //这里是与C#服务端通信的需求,我是检测是否正常连接用的.
}
Message message = new Message();
message.what = 1; //标识符为1,表明显示在自己的消息框
Bundle bundle = new Bundle();
bundle.putString("msg", result); //将读取到的信息传入handler中处理.
message.setData(bundle);
handler.sendMessage(message);
}
//发送消息,这里直接使用mysocket.getOutputStream()也可以.
DataOutputStream writer = new DataOutputStream(mysocket.getOutputStream());
writer.write(clientMessage.getText().toString().getBytes()); //发送消息
//发送,我也要写入handler中.
Message message = new Message();
message.what = 1; //标识符为1,表明显示在自己的消息框
Bundle bundle = new Bundle();
bundle.putString("msg", myIp+" : "+clientMessage.getText().toString()); //ip + 说明
message.setData(bundle);
handler.sendMessage(message);
//Handler
public Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what==1){
Bundle data = msg.getData();
sb.append(data.getString("msg")); //StringBuffer sb = new StringBuffer();这里直接不用这个也可以.
sb.append("\n");
serverMessageText.setText(sb.toString());
}
}
};
Server服务端端核心代码
//设置一个端口,监听客户端的连接,监听手机服务端50000端口.
serverSocket = new ServerSocket(50000); //绑定sport
clientSocket = serverSocket.accept(); //serverSocket是该服务器的,clientSocket返回客户端的ip和端口.
//clientSocket.toString返回的是socket(192.168.1.107 + port)
//userText.setText(clientSocket.toString()); 报错???,使用handler处理成功.
//读取消息,开启一个子线程,反复监听消息.
while(true){
//一开始客户端能给服务端发消息,服务端不能给客户端发消息,幸好解决了
InputStream is = clientSocket.getInputStream();
byte[] buffer = new byte[1024*1024];
int len = is.read(buffer);
String result = new String(buffer, 0, len); //读消息跟发送消息与客户端几乎一致.
Message message = new Message();
Bundle bundle = new Bundle();
bundle.putString("msg",result);
message.setData(bundle);
message.what = 1; //标识符为1
handler.sendMessage(message);
}
//发送消息,也是需要开启一个线程.
OutputStream writer = clientSocket.getOutputStream();
writer.write(normalMessage.getText().toString().getBytes()); //发给1看看.
String result = "发送成功";
Message message = new Message();
Bundle bundle = new Bundle();
bundle.putString("msg",result);
message.setData(bundle);
//发送handler,更新ui
message.what=1;
handler.sendMessage(message);
@SuppressLint("HandlerLeak")
public Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what==1){
Bundle data = msg.getData();
sb.append(data.getString("msg"));
sb.append("\n");
normalText.setText(sb.toString());
}
}
};
主界面中的图片切换动作使用handler处理和动画处理.
ListView客户端和ListView服务端在以上基础上,使用listview组件来显示消息,这里我对格式弄了一个处理,因此可能无法使用ListView客户端来与c#客户端进行数据交换,而只能使用Android与Android进行通信,可以解决该问题,如下.
//Server服务端发送消息
String result = userText.getText().toString() + "-" + classText.getText().toString() + "-" + ageText.getText().toString();
//发送的是userText 内容 classText 内容 ageText内容 中间使用 - 来分割,这样容易把一串字节流按指定格式分割成我们想要的部分.
writer.write(result.getBytes());
//Client客户端
Text = result.split("-"); //按分开.
HashMap<String,Object> map = new HashMap<String, Object>();
map.put("User",Text[0]);
map.put("Class",Text[1]);
map.put("Age",Text[2]);
mylist.add(map);
//我们发现,若C#服务端发送过来的消息不包含-因此Text[0] = result,Text[1],Text[2]抛出下标越界异常.
//修改.
int i=0;
for(i=0;i<result.length();i++){
if (result.charAt(i)=='-'){
break;
}
}
if (i==result.length()){
//说明是C#发送过来的,对Text进行处理.
Text[0] = result;
Text[1] = "null";
Text[2] = "null";
}else{
Text = result.split("-"); //按分开.
}
Java split测试
一些总结:
1.服务端(假设是模拟机)可以向手机(服务端)发送请求连接,因此知道手机的ip地址能够正常连接,而手机客户端无法通过电脑的ip地址访问到模拟机(服务端),若要连接,需要知道模拟机的ip地址.
2.一个Message只能传给一个handler,若要使用handler处理多个任务,需要初始化多个Message.
3.可以使用bundle向handler中(可以是同一个活动)传递数据,在handler中使用Bundle bundle = msg.getData()来获取数据。
4.在退出活动的时候,需要关闭I/O流和socket连接.
5.使用5个write,怎么第一个输出有换行,明明程序中没有换行,最后写成一行可以解决该问题.
(若不写成一个write,可以通过trim()方法去掉多余的空格和换行)
6.Handler是Android提供的一个用来更新UI的机制(Android不允许在子线程更新UI),也是一个消息处理的机制
7.一些超时的任务处理,如网络下载等需要使用子线程来完成,因此默认情况下,主线程等待5s以上就会关闭该活动。
功能:
1.在C#Socket通信的基础上,增加Android Socket通信
2.能够让Android跟C#通信
3.能够让Android与Android进行通信.
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)