文章目录
项目已上传
前言
实验设备:yodo实验箱、笔记本电脑
要求:
1.读懂温湿度功能、继电器功能、光照度功能模块的代码
2.添加led灯控制、PWM调光控制模块代码
说明:
1.底层功能实现代码老师已给出,在MyApplication.java中
2. 将老师提供的串口通信所用文件jni和jnLibs复制到main文件下
3. 将老师提供的图片添加到mipmap文件夹中
4. 在build.graddle中添加代码
externalNativeBuild{
ndkBuild{
path'src/main/jni/Android.mk'
}
}
报告
代码
清单文件:AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.exp6_03195020">
<uses-permission android:name="android.permission.INTERNET"/><!--添加网络权限-->
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"><!--app启动时关联MyApplication-->
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
页面布局:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:orientation="vertical"
android:background="#a9a7a7"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@mipmap/tempback"
android:gravity="center"
android:text="服务端"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@mipmap/tempback"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="120dp"
android:layout_weight="1">
<ImageView
android:id="@+id/iv1"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:src="@mipmap/temp"/>
<TextView
android:id="@+id/temp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@+id/iv1"
android:text="0℃"
android:textColor="#de0909"
android:textSize="20dp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<ImageView
android:id="@+id/iv2"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:src="@mipmap/hehum"/>
<TextView
android:id="@+id/hehum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@+id/iv2"
android:text="0%"
android:textColor="#de0909"
android:textSize="20dp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
>
<ImageView
android:id="@+id/iv3"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:src="@mipmap/guangzhao"/>
<TextView
android:id="@+id/guangzhao"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@+id/iv3"
android:text="0Lux"
android:textColor="#de0909"
android:textSize="20dp"/>
</RelativeLayout>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@mipmap/tempback">
<ImageView
android:id="@+id/iv_jiadian"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:src="@mipmap/jidian"/>
<Button
android:id="@+id/bt1"
android:layout_width="70dp"
android:layout_height="30dp"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/iv_jiadian"
android:onClick="kongzhi"/>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@mipmap/tempback"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="120dp"
android:layout_weight="1">
<Button
android:id="@+id/led_red"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:background="@mipmap/c_light_off" />
<TextView
android:id="@+id/text_red"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/led_red"
android:layout_centerHorizontal="true"
android:text="红灯"
android:textColor="#DD001B"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="120dp"
android:layout_weight="1">
<Button
android:id="@+id/led_white"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:background="@mipmap/c_light_off" />
<TextView
android:id="@+id/text_white"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/led_white"
android:layout_centerHorizontal="true"
android:text="白灯"
android:textColor="#2EBCF4"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="120dp"
android:layout_weight="1">
<Button
android:id="@+id/led_green"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:background="@mipmap/c_light_off" />
<TextView
android:id="@+id/text_green"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/led_green"
android:layout_centerHorizontal="true"
android:text="绿灯"
android:textColor="#59A869"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="120dp"
android:layout_weight="1">
<Button
android:id="@+id/led_yellow"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:background="@mipmap/c_light_off" />
<TextView
android:id="@+id/text_yellow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/led_yellow"
android:layout_centerHorizontal="true"
android:text="黄灯"
android:textColor="#FFE14D"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="120dp"
android:layout_weight="1">
<Button
android:id="@+id/led_all"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:background="@mipmap/button_off" />
</RelativeLayout>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@mipmap/tempback">
<SeekBar
android:id="@+id/seekBar"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="0"/>
</RelativeLayout>
</LinearLayout>
默认页面:MainActivity.java
package com.example.exp6_03195020;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android_serialport_api.SerialPort;
public class MainActivity extends AppCompatActivity {
private MyApplication myApplication;//全局Application对象
private SerialPort serialPort;//串口对象
private InputStream inputStreamChuanKou;//串口输入流
private OutputStream outputStreamChuanKou;//串口输出流
private TextView wendu, shidu, guangzhaodu;//文本控件对象
private Button bt1;//按钮控件对象
private boolean jidianqi = true;//继电器开关布尔量
//================<<<<< !!!(此注释标志为添加部分,以下再次出现不再解释)!!!
//==============================添加功能1:led灯控制===============================
private Button btred,btwhite,btgreen,btyellow,btall;//按钮控件对象
private boolean redled = true;//红灯开关布尔量
private boolean whiteled = true;//红灯开关布尔量
private boolean greenled = true;//红灯开关布尔量
private boolean yellowled = true;//红灯开关布尔量
private boolean allled = true;//红灯开关布尔量
//==============================添加功能2:调光灯控制====================================================
private SeekBar seekBar;//拖动条控件对象
private Context mContext;//上下文对象
private byte[] cmd = {(byte) 0xCC, (byte) 0xEE, (byte) 0x01, (byte) 0x09, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFF};//通信协议字节数组
//==================>>>>>
//串口数据接收Handler
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {//重写handlerMessage方法
byte[] data = msg.getData().getByteArray("data");//从消息中提取 data字段内容
//接收到串口上传来的温湿度数据后进行判断
if (data[3] == (byte) 0x03 && data[4] == (byte) 0x01) {//判断消息类型是否为温湿度
byte byteXH = data[5];//获取温度高位数据
byte byteXL = data[6];//获取温度低位数据
byte byteYH = data[7];//获取湿度高位数据
byte byteYL = data[8];//获取湿度高位数据
wendu.setText("温度:" + String
.valueOf((byteXH * 256 + byteXL) / 100));//在文本框控件显示温度
shidu.setText("湿度:" + String
.valueOf((byteYH * 256 + byteYL) / 100));//在文本框控件显示湿度
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {//重写Activity的onCreate函数,系统创建Activity时调用
super.onCreate(savedInstanceState);//调用父类的onCreate
setContentView(R.layout.activity_main);//为页面加载布局
myApplication = (MyApplication) getApplication();//获取全局Application对象
wendu = findViewById(R.id.temp);//获取温度文本框控件对象
shidu = findViewById(R.id.hehum);//获取湿度文本控件对象
guangzhaodu = findViewById(R.id.guangzhao);//获取光照度文本控件对象
bt1 = findViewById(R.id.bt1);//获取按钮控件对象
//===============<<<<<
init();//调用init函数,实现对led灯的控制
mContext = this;//获取上下文对象
PWM();//调用PWM函数,实现对调光灯的控制
//===============>>>>>>
try {
serialPort = myApplication.getSerialPort("/dev/ttyAMA5");//打开串口
inputStreamChuanKou = serialPort.getInputStream();//获取串口输入流
outputStreamChuanKou = serialPort.getOutputStream();//获取串口输出流
} catch (IOException e) {//处理例外
e.printStackTrace();
}
new Thread(new Runnable() {//创建串口接收进程
@Override
public void run() { //重写线程的 run方法
byte[] date = new byte[16];//创建字节数组
int len = -1;//定义长度变量
try {
len = inputStreamChuanKou.read(date);
while (len != -1) {//循环读取串口的data数组
Message message = new Message();//创建消息对象
Bundle bundle = new Bundle();//创建数据包对象
bundle.putByteArray("data", date);//将data数据存入数据包的data字段
message.setData(bundle);//将数据包对象封装进消息
handler.sendMessage(message);//向串口接收Handler发送消息
}
} catch (IOException e) {//处理IO例外
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {//处理其它例外
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();//开启串口接收线程
myApplication.setOnConnectListener(new MyApplication.ConnectListener() {//设置myApplication的ConnectListener
@Override
public void onReceiveData(byte[] buffer) { //重写ConnectListener的onReceiveData函数,接收到 wifi socket 上的光照度数据
if (buffer[3] == (byte) 0x02 && buffer[4] == (byte) 0x01) {//判断消息类型是否为光照度
byte byteXH = buffer[5];//获取光照度高位数据
byte byteXL = buffer[6];//获取光照度低位数据
guangzhaodu.setText("光照度:" + String.valueOf((byteXH * 256 + byteXL)));//在页面文本框控件上显示光照度
}
}
});
}
public void kongzhi(View view) { //在串口上发送控制继电器指令
if (jidianqi) {//继电器状态若为真,为关闭状态
jidianqi = false;//先将继电器状态置为假
bt1.setBackgroundResource(R.mipmap.on);//设置继电器图片控件背景-打开
byte[] cmd_on = {(byte) 0xCC, (byte) 0xEE, (byte) 0x01, (byte) 0x18, (byte) 0x01,
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFF};//生成继电器开关质量协议消息
try {
outputStreamChuanKou.write(cmd_on);//在串口输入流上发送打开继电器指令
outputStreamChuanKou.flush();//刷新串口输入流
} catch (IOException e) {//处理IO例外
e.printStackTrace();
}
} else {//继电器状态若为假,为打开状态
jidianqi = true;//先将继电器状态置为真
bt1.setBackgroundResource(R.mipmap.off);//设置继电器图片控件背景-关闭
byte[] cmd_off = {(byte) 0xCC, (byte) 0xEE, (byte) 0x01, (byte) 0x18, (byte) 0x02,
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFF};//生成继电器开关质量协议消息
try {
outputStreamChuanKou.write(cmd_off);//在串口输入流上发送关闭继电器指令
outputStreamChuanKou.flush();//刷新串口输入流
} catch (IOException e) {//处理IO例外
e.printStackTrace();
}
}
}
//=========================<<<<<
//===============================调光灯==================================
private void PWM() { //控制调光灯
seekBar = findViewById(R.id.seekBar);
cmd[3] = (byte) 0x0A;
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
//进度发生改变时会触发
cmd[4] = (byte) Integer.parseInt(Integer.toHexString(progress/10),16);
try {
outputStreamChuanKou.write(cmd);
outputStreamChuanKou.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
//按住SeekBar时会触发
Toast.makeText(mContext,"正在调节亮度",Toast.LENGTH_SHORT).show();
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//放开eekBar时会触发
Toast.makeText(mContext,"停止调节亮度",Toast.LENGTH_SHORT).show();
}
});
}
//===============================LED================================
private void init() { //初始化led灯
btred = findViewById(R.id.led_red);//获取红灯按钮对象
btwhite = findViewById(R.id.led_white);//获取白灯按钮对象
btgreen = findViewById(R.id.led_green);//获取绿灯按钮对象
btyellow = findViewById(R.id.led_yellow);//获取黄灯按钮对象
btall = findViewById(R.id.led_all);//获取全部灯按钮对象
btred.setOnClickListener(new View.OnClickListener() {//设置红灯点击事件监听器
@Override
public void onClick(View v) {//重写onClick方法
enlightred();//调用红灯控制函数enlightred
}
});
btwhite.setOnClickListener(new View.OnClickListener() {//设置白灯点击事件监听器
@Override
public void onClick(View v) {//重写onClick方法
enlightwhite();//调用白灯控制函数enlightred
}
});
btgreen.setOnClickListener(new View.OnClickListener() {//设置绿灯点击事件监听器
@Override
public void onClick(View v) {//重写onClick方法
enlightgreen();//调用绿灯控制函数enlightred
}
});
btyellow.setOnClickListener(new View.OnClickListener() {//设置黄灯点击事件监听器
@Override
public void onClick(View v) {//重写onClick方法
enlightyellow();//调用黄灯控制函数enlightred
}
});
btall.setOnClickListener(new View.OnClickListener() {//设置全部灯点击事件监听器
@Override
public void onClick(View v) {//重写onClick方法
enlightall();//调用全部灯控制函数enlightred
}
});
}
public void enlightred(){//红灯控制函数
if (redled){//若红灯状态为真,为关闭状态
redled = false;//先设置红灯状态为假
cmd[3] = (byte) 0x09;//按通信协议修改指令
cmd[4] = (byte) 0x01;
btred.setBackgroundResource(R.mipmap.c_light_red);//设置红灯背景控件为打开图片
myApplication.send(cmd);//调用myApplication的send方法发送指令
}else {//若红灯状态为假,为打开状态
redled = true;//先设置红灯状态为真
cmd[3] = (byte) 0x09;//按通信协议修改指令
cmd[4] = (byte) 0x02;
btred.setBackgroundResource(R.mipmap.c_light_off);//设置红灯背景控件为关闭图片
myApplication.send(cmd);//调用myApplication的send方法发送指令
}
}
public void enlightwhite(){//白灯控制函数
if (whiteled){
whiteled = false;
cmd[3] = (byte) 0x09;
cmd[4] = (byte) 0x03;
btwhite.setBackgroundResource(R.mipmap.c_light_white);
myApplication.send(cmd);
}else {
whiteled = true;
cmd[3] = (byte) 0x09;
cmd[4] = (byte) 0x04;
btwhite.setBackgroundResource(R.mipmap.c_light_off);
myApplication.send(cmd);
}
}
public void enlightgreen(){//绿灯控制函数
if (greenled){
greenled = false;
cmd[3] = (byte) 0x09;
cmd[4] = (byte) 0x05;
btgreen.setBackgroundResource(R.mipmap.c_light_green);
myApplication.send(cmd);
}else {
greenled = true;
cmd[3] = (byte) 0x09;
cmd[4] = (byte) 0x06;
btgreen.setBackgroundResource(R.mipmap.c_light_off);
myApplication.send(cmd);
}
}
public void enlightyellow(){//黄灯控制函数
if (yellowled){
yellowled = false;
cmd[3] = (byte) 0x09;
cmd[4] = (byte) 0x07;
btyellow.setBackgroundResource(R.mipmap.c_light_yellow);
myApplication.send(cmd);
}else {
yellowled = true;
cmd[3] = (byte) 0x09;
cmd[4] = (byte) 0x08;
btyellow.setBackgroundResource(R.mipmap.c_light_off);
myApplication.send(cmd);
}
}
public void enlightall(){//全部灯控制函数
if (allled){
allled = false;
cmd[3] = (byte) 0x09;
cmd[4] = (byte) 0x0c;
btred.setBackgroundResource(R.mipmap.c_light_red);
btwhite.setBackgroundResource(R.mipmap.c_light_white);
btgreen.setBackgroundResource(R.mipmap.c_light_green);
btyellow.setBackgroundResource(R.mipmap.c_light_yellow);
btall.setBackgroundResource(R.mipmap.button_on);
myApplication.send(cmd);
}else {
allled = true;
cmd[3] = (byte) 0x09;
cmd[4] = (byte) 0x0d;
btred.setBackgroundResource(R.mipmap.c_light_off);
btwhite.setBackgroundResource(R.mipmap.c_light_off);
btgreen.setBackgroundResource(R.mipmap.c_light_off);
btyellow.setBackgroundResource(R.mipmap.c_light_off);
btall.setBackgroundResource(R.mipmap.button_off);
myApplication.send(cmd);
}
}
//======================>>>>>
}
自定义Application类:MyApplication.java
package com.example.exp6_03195020;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.InvalidParameterException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import android_serialport_api.SerialPort;
public class MyApplication extends android.app.Application {//自定义Application类
private Map<String, SerialPort> serialPortMap = new HashMap<String, SerialPort>(); //定义串口列表
private static MyApplication instance;//创建MyApplication的实例对象
//Application 的回掉方法
public static final MyApplication getInstance() {//目前本项目未调用!!!
return instance;
}
public SerialPort getSerialPort(String path) throws SecurityException, //打开并读取串口状态参数
IOException, InvalidParameterException {
return getSerialPort(path, 115200);///调用 getSerialPort(String path,int baudrate)
}
public SerialPort getSerialPort(String path, int baudrate) //打开串口并返回串口参数
throws SecurityException, IOException, InvalidParameterException {
System.out.println("MyApplication 启动");//输出串口启动信息
SerialPort mSerialPort = serialPortMap.get(path);//按照路径从串口列表获取串口对象
if (mSerialPort == null) {//如果读取结果为空
/* Check parameters 检查参数 */
if ((path.length() == 0) || (baudrate == -1)) {//检查串口路径参数是否错误
throw new InvalidParameterException();
}
/* Open the serial port 打开串口 使用指定的端口名、波特率和奇偶校验位初始化 */
mSerialPort = new SerialPort(new File(path), baudrate, 0);//创建新的串口对象
serialPortMap.put(path, mSerialPort);//将串口对象插入串口列表
}
return mSerialPort;//返回串口对象
}
public void closeSerialPort() { //关闭串口,目前本项目未调用!!!
for (SerialPort mSerialPort : serialPortMap.values()) {
if (mSerialPort != null) {
mSerialPort.close();
}
}
serialPortMap.clear();
}
// --------------socket 通信--------
private Socket socket = null;//创建Socket对象
private ServerSocket serverSocket = null;//创建按ServerSocket对象
public static OutputStream outputStream; //输出流
private static ConnectListener mListener; // 接收接口类
final LinkedList<Socket> list = new LinkedList<Socket>(); //socket 列表
@Override
public void onCreate() {//重写Application的OnCreate()函数,该函数被系统自动调用
// TODO Auto-generated method stub
super.onCreate();//调用父类的onCreate()
//启动服务端
ServerListeners listener1 = new ServerListeners(); //创建 socket 监听进程
listener1.start(); //启动 socket 监听进程
}
//接口回调
public interface ConnectListener { //接收接口类定义
void onReceiveData(byte[] buffer); //接收数据函数在主程序 activity 中实现
}
public void setOnConnectListener(ConnectListener linstener) {//设置接收接口类
this.mListener = linstener;
} //设置接收接口类
Handler mHandler = new Handler() { //接收 handler,处理socket接收到的数据
public void handleMessage(Message msg) {
switch (msg.what) {
case 100://判断消息类型为100
if (mListener != null) {
mListener.onReceiveData(msg.getData().getByteArray("data"));//调用接收接口的onReceiveData字段内容
}
break;
}
}
};
/**
* 处理 Socket 请求的线程类
*/
class Task implements Runnable { //接收子线程
private Socket socket;//创建socket对象
/**
* 构造函数
*/
public Task(Socket socket) {
this.socket = socket;
}
@Override
public void run() {//重写run方法
while (true) {
int size;//定义读取长度
try {
InputStream inputStream = null; //定义输入流
inputStream = socket.getInputStream();//获取socket输入流
byte[] buffer = new byte[16];//定义接收字节数组
size = inputStream.read(buffer);//读取输入流到buffer,获取读取到数组的字节长度
if (size > 0) {//如果长度大于0
Message message = new Message();//创建消息对象
message.what = 100;//定义消息类型为100
Bundle bundle = new Bundle();//创建消息数据包
bundle.putByteArray("data", buffer);//将buffer数据放入消息包的data字段
message.setData(bundle);//将数据包封装进消息
mHandler.sendMessage(message);//向mHandler发送消息
}
} catch (Exception e) {//处理例外
e.printStackTrace();
return;
}
}
}
}
public class ServerListeners extends Thread { //socket 监听线程
@Override
public void run() {//重写run方法
try {
serverSocket = new ServerSocket(7777);//创建监听套接字,端口为7777
while (true) {
System.out.println("等待客户端请求....");//输出“等待客户端请求...”
socket = serverSocket.accept();//接收对方连接请求,建立绘画套接字
System.out.println("收到请求,服务器建立连接...");//成功接收请求,输出提示消息
System.out.println("客户端" + socket.getInetAddress().getHostAddress() + "连接成功");//输出客户端地址消息
System.out.println("客户端" + socket.getRemoteSocketAddress() + "连接成功");//输出客户端地址信息
list.add(socket);//将会话套接字插入套接字列表
//每次都启动一个新的线程
new Thread(new Task(socket)).start(); //启动接收子线程
}
} catch (IOException e) {//处理例外
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 发送数据
*
* @param bytes 需要发送的内容
*/
public void send(byte[] bytes) { //Socket发送数据函数,供主程序调用
System.out.println(list.size());//输出Socket列表长度
for (Socket s : list) {//在列表里的所有Socket上发送消息
System.out.println("客户端" + s.getInetAddress().getHostAddress());//输入客户端地址信息
try {
outputStream = s.getOutputStream();//获取输出流
if (outputStream != null) {//如果输出流不为空
outputStream.write(bytes);//在输出流发送byte数据
outputStream.flush();//刷新输出流
}
} catch (IOException e) {//处理 io 例外
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {//处理其他例外
System.out.println("客户端 socket 不存在。");
}
}
}
/**
* 断开连接
*
* @throws IOException
*/
public void disconnect() throws IOException {//关闭Socket连接函数,目前本项目未调用!!!
System.out.println("客户端是否关闭 1");
if (list.size() != 0) {
for (Socket s : list) {
s.close();
System.out.println("客户端是否关闭 2");
}
}
if (outputStream != null)
outputStream.close();
list.clear();
}
}
附:通信协议