云主机与外网主机、Android手机端的socket通信
来源:互联网 发布:完美丈夫网络剧 编辑:程序博客网 时间:2024/06/05 06:06
这段时间一直在忙着弄这个东西,做一个服务器能够与外网主机和手机客户端保持一个实时的通信,不断地进行信息的交互。现在很多IT公司都已经做出了成熟的技术解决方案,但是使用过程有点。。繁琐?,还有这些服务器都是要付费的,要花不少钱,作为学生狗自己动手撸。我弄这个花了不少时间,期间试过了百度云、京东云、阿里云(阿里云最坑,公网IP连不上,貌似不止我才这样,其他人买的esc实例也经常连不上),试了这么多还好都是学生优惠,不然心都是在滴血的。最后我用腾讯云基本实现了我想要的功能(还是免费体验的,太实惠了)。下面进入正题首先购买腾讯云云服务器,按照腾讯云官网的说明选择配置,一步一步下去;连接云服务器的教程官网也有的,用电脑的远程桌面连接比较好,最好选择一个盘作为共享文件,这样你的电脑与云服务器之间传输文件比较方便;安装eclipse和java sdk ,别忘了配置环境变量。下面是服务端代码:
package test;import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; public class Server { public static final int PORT = 8800;//监听的端口号 public static void main(String[] args) { System.out.println("服务器启动...\n"); Server server = new Server(); server.init(); } public void init() { try { ServerSocket serverSocket = new ServerSocket(PORT); while (true) { //堵塞 Socket client = serverSocket.accept(); new HandlerThread(client); } } catch (Exception e) { System.out.println("服务器异常: " + e.getMessage()); } } private class HandlerThread implements Runnable { private Socket socket; public HandlerThread(Socket client) { socket = client; new Thread(this).start(); } public void run() { try { // 读取客户端数据 DataInputStream input = new DataInputStream(socket.getInputStream()); String clientInputStr = input.readUTF();//这里要注意和客户端输出流的写方法对应,否则会抛 EOFException // 处理客户端数据 System.out.println("客户端:" + clientInputStr); // 向客户端回复信息 DataOutputStream out = new DataOutputStream(socket.getOutputStream()); System.out.print("请输入:\t"); // 发送键盘输入的一行 String s = new BufferedReader(new InputStreamReader(System.in)).readLine(); out.writeUTF(s); out.close(); input.close(); } catch (Exception e) { System.out.println("服务器异常: " + e.getMessage()); } finally { if (socket != null) { try { socket.close(); } catch (Exception e) { socket = null; System.out.println("服务端异常:" + e.getMessage()); } } } } } }
注意:最好不在主线程中去进行连接,一、如果因为网络原因,程序可能回一直卡在那;二、现在很多时候已经不允许在你在主线程中去进行网络有关的操作了。最保险的做法还是新开一个线程去处理这些事情。云主机必须关闭防火墙,查看开放的端口和端口是否被占用。
先来电脑客户端:
package client;import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; public class Client { public static final String IP= "123.207.xx.xx";//服务器地址 public static final int PORT = 8800;//服务器端口号 String DemoAirData=null; public static void main(String[] args) { System.out.println("客户端启动..."); System.out.println("当接收到服务器端字符为 \"Exit\" 的时候, 客户端退出\n"); while (true) { Socket socket = null; try { socket = new Socket(IP, PORT); //读取服务器端数据 DataInputStream input = new DataInputStream(socket.getInputStream()); //向服务器端发送数据 DataOutputStream out = new DataOutputStream(socket.getOutputStream()); System.out.print("请输入: \t"); String str = new BufferedReader(new InputStreamReader(System.in)).readLine(); out.writeUTF(str); String ret = input.readUTF(); System.out.println("服务器端: " + ret); // 如接收到 "OK" 则断开连接 if ("OK".equals(ret)) { System.out.println("客户端将关闭连接"); Thread.sleep(500); break; } out.close(); input.close(); } catch (Exception e) { System.out.println("客户端异常:" + e.getMessage()); } finally { if (socket != null) { try { socket.close(); } catch (IOException e) { socket = null; System.out.println("客户端异常:" + e.getMessage()); } } } } } }
服务器端与客户端的读和写的方法要一致。运行后,服务端和客户端可以反复的进行聊天。
最后是手机客户端:
activit_main.xml代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.administrator.csdn_test2.MainActivity"> <Button android:id="@+id/connect" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/user" android:text="连接"/> <TextView android:id="@+id/text" android:layout_width="match_parent" android:layout_height="120dp" android:layout_below="@+id/connect" /> <EditText android:id="@+id/edit" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/text" android:hint="输入信息"/> <Button android:id="@+id/send" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/edit" android:text="发送"/></LinearLayout>
放了四个控件,两个button,一个textview,一个editview,比较简单。
下面是MainActivity
package com.example.administrator.csdn_test2;import android.os.Handler;import android.os.Message;import android.os.StrictMode;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.Socket;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends AppCompatActivity { EditText editText; TextView textView; Button connect; public static final int TEXT= 1 ; public static final int SEND=2; public static final int CONNECT=3; String readmsg; private static final int REQUEST_EXTERNAL_STORAGE = 1 ; public static final String IP = "123.207.xx.xx";//服务器地址 public static final int PORT = 8800;//服务器端口号 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); System.out.println("客户端启动..."); editText = (EditText) findViewById(R.id.edit); textView = (TextView) findViewById(R.id.text); connect=(Button)findViewById(R.id.connect); Button send=(Button)findViewById(R.id.send); send.setEnabled(true); StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads(). detectDiskWrites().detectNetwork().penaltyLog().build()); connect.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View arg0) { new myThread().start(); } }); } class myThread extends Thread{ @Override public void run(){ Socket socket=null; while (true){ try{ Button send=(Button)findViewById(R.id.send); socket=new Socket(IP,PORT); final DataOutputStream dataOutputStream=new DataOutputStream(socket.getOutputStream()); DataInputStream dataInputStream=new DataInputStream(socket.getInputStream()); //Toast.makeText(MainActivity.this,"连接成功",Toast.LENGTH_SHORT).show(); Message message3=new Message(); message3.what=CONNECT; handler.sendMessage(message3); send.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { if (editText.length()==0){ //什么都不做为了防止发空消息 }else { try{ String string=editText.getText().toString(); dataOutputStream.writeUTF(string); Message message2=new Message(); message2.what=SEND; handler.sendMessage(message2); }catch (IOException e){ e.printStackTrace(); } } } }); readmsg=dataInputStream.readUTF(); Message message1=new Message(); message1.what=TEXT; handler.sendMessage(message1); }catch (IOException e){ e.printStackTrace(); } } } } public Handler handler=new Handler(){//异步消息处理,不能直接在主线程中更新UI,否则会程序会崩溃! public void handleMessage(Message msg){ switch (msg.what){ case TEXT: textView.setText(readmsg); Toast.makeText(MainActivity.this,"收到消息!",Toast.LENGTH_SHORT).show(); break; case SEND: editText.setText("");//清空输入框 Toast.makeText(MainActivity.this,"发送成功",Toast.LENGTH_SHORT).show(); break; case CONNECT: Toast.makeText(MainActivity.this,"连接成功",Toast.LENGTH_SHORT).show(); connect.setEnabled(true); default: break; } } };}
AndroidManifest.xml中添加权限,android 23以上还需要在java代码中申请权限(我在这里把权限加在application里面又会出错)
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
服务器运行效果
手机端
第一次写博客,时间紧迫就写这么多了,有许多地方也许讲的很浅显,但这都实践得来的经验,对于在下实属不易。希望大家多多指点,共同进步!
阅读全文
0 0
- 云主机与外网主机、Android手机端的socket通信
- 外网主机与内网主机通信 路由端口映射
- Socket主机与客户机通信难点
- VirtualBOX Linux与主机Windows Socket 通信
- 本地主机与云服务器主机建立socket套接字进行通信小记
- 主机与虚拟机通信
- 实现本地主机与阿里云服务器的UDP通信
- 关于TQ2440与主机通信的心得
- 主机与虚拟机上的ubuntu通信
- 主机与虚拟机相互通信及虚拟机访问外网
- Centos7通过NAT实现与主机的通信,并且连接外网
- 主机与虚拟机通信设置
- 主机与namespace建立通信
- linux客户端与主机通信
- 局域网内主机之间Socket通信实现
- android在wifi下手机与电脑的socket通信
- android在wifi下手机与电脑的socket通信
- 交换机下接非vlan1的主机,实现主机与路由器的通信配置方法
- 泛型总结
- iOS把图片缓存到本地的几种方法
- 深入理解Java类加载器(1)
- JAVA12
- Error creating bean with name 'org.springframework.validation.beanvalidation.LocalValidatorFactoryBe
- 云主机与外网主机、Android手机端的socket通信
- mybatis的理解
- ionic providers的使用
- 中间件的理解
- springboot+maven+springdata jpa +querydsl快速实现增删改查分页
- 手机网上商城-项目经验总结(二)-创建项目结构
- javaBean验证框架(6)—附加约束和组合约束
- 手机网上商城-项目经验总结(三)-QueryRunner
- HDU5514 Frogs (gcd + 容斥原理)