多线程实例讲解——服务器与WiFi模块通过Socket通信

如果要找线程与进程的区别,可以转车了哈。
首先说一下我的目的:
我有一个WiFi模块我希望将其获取到的数据传给我的服务器,服务器一直监听某个端口,然后将收到的数据进行处理,再存入数据库,之后的操作就是显示页面了。
因为服务器一直在监听有没有收到信息,或者说是否有连接,那么思路就是主线程是一直监听某个这个信息或者端口,一旦有阻塞(说明有人发数据),就创建一个子线程来接收并处理这个信息


**模拟的客户端**:模拟向服务器一直发送数据,并也可以接收服务器传回来的信息(copy)
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.Scanner;

public class Client {  
    public static final String IP_ADDR = "XXX.XX.XX.XX";//服务器地址   
    public static final int PORT = XXXX;//服务器端口号    
      
    public static void main(String[] args) {    
        System.out.println("客户端启动...");    
        
        String str="";
       
        while (true) {    
            Socket socket = null;  
            try {  
                //创建一个流套接字并将其连接到指定主机上的指定端口号  
                socket = new Socket(IP_ADDR, PORT);    
                    
                //读取服务器端数据    
                DataInputStream input = new DataInputStream(socket.getInputStream());    
                //向服务器端发送数据    
                DataOutputStream out = new DataOutputStream(socket.getOutputStream());    

//              客户端一直发送数据
                str ="#ttt.89#,#gyff.90#,";

                out.writeUTF(str); 
                out.flush();
                String ret = input.readUTF();     
                System.out.println("服务器端返回过来的是: " + ret);    
                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("客户端 finally 异常:" + e.getMessage());   
                    }  
                }  
            }  
        }    
    }    
}

这只是一个简单的java类而已也不涉及多线程,通过out.writeUTF(str); 写入你想发给服务端的数据。


**服务器主要代码**:
public class MyTestMybatis { 
	
	public static final int PORT = XXX;//监听的端口号 ,与客户端的端口号一样
/**	
这里是我的一些操作数据库的函数
	*/

	
	
	public static void main(String[] args) throws IOException, ParseException {
		// TODO Auto-generated method stub    
	
		System.out.println("服务器启动...\n");    
        MyTestMybatis server = new MyTestMybatis();
      //日期格式只要时分秒
      	SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");
      	//课程时间,或者说检测开始,或者说在某个范围内开启服务器
        String classtime1="20:25:00";
        Date class_Date1 = sdf.parse(classtime1);//将其转化为
        String classtime2="20:35:00";
        Date class_Date2 = sdf.parse(classtime2);//将其转化为毫秒

      //获取当前时间        
        Date now_Date2 = new Date();

        now_Date2 = sdf.parse(sdf.format(now_Date2));

//        如果时间在某个范围内就进去将当前检测到的mac地址的学生是否迟到置为1
//		如果课程时间与当前时间相等,就开启服务器检测
        	if(  class_Date1.getTime() < now_Date2.getTime()&&class_Date2.getTime()>now_Date2.getTime()){
        		server.init();在这里调用服务器的初始化函数,所有的操作都在这里进行,相当于这是一个主线程
        	}
        	
//        	如果时间在凌晨00:00点,就把数据改回去
        	String back_time = "00:00:00";
    		Date back_date = sdf.parse(back_time);
        	if(back_date.getTime() == now_Date2.getTime()) {
        		//将学生数据还原
        		updateStudentBack();
        	}
         
         
	}
	
	
	public void init() {    
	这里相当于主线程,用来接收客户端连接
        try {    
            ServerSocket serverSocket = new ServerSocket(PORT);    
            while (true) { 
                // 一旦有堵塞, 则表示服务器与客户端获得了连接    
                Socket client = serverSocket.accept(); 
               
              System.out.println("连接成功,并打印对方ip");
              System.out.println(client.getRemoteSocketAddress());
              
                // 处理这次连接   ,每次有连接都会创建一个新的线程去执行 
                new HandlerThread(client);
                //线程叫HandlerThread,信息存在socket当中,继续往下走,到线程的内部
                
            }
        } catch (Exception e) {    
            System.out.println("服务器异常: " + e.getMessage());    
        }    
    }    
    
    private class HandlerThread implements Runnable {    
    //HandlerThread 继承Runnable 接口,便成为一个线程
        private Socket socket;    
        public HandlerThread(Socket client) { 
        //构造函数   
            socket = client;    
            new Thread(this).start();  //这里会调用你的线程run方法  
        }     
    
        public void run() {    
            try {    
                // 读取客户端数据    
                DataInputStream input = new DataInputStream(socket.getInputStream());  
                //sty/5/1
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(input));
                
                
//                这里获取到数据
               // String clientInputStr = input.readUTF();//这里要注意和客户端输出流的写方法对应,否则会抛 EOFException  

                String clientInputStr = bufferedReader.readLine();
                
                
          
                
                // 处理客户端数据    
                System.out.println("客户端发过来的内容:" + clientInputStr);  
                
                
                //用来存到过的MAC地址
                //HashMap<String,Integer> hashmapIP = new HashMap<>(); 
//                hashmapIP = new HashMap<>(); 应该在最开始定义
                
                //用字符串数组来接收
                String str[] = clientInputStr.split(",");
                
                for(int i = 0;i < str.length;i++){
                	System.out.println("第"+i+"个"+"MAC地址为"+str[i]);
                	updateStudentLate(1,str[i]);
                	//如果当前hashmap中有MAC,就应该不管,没有就把来了的次数加1,并且存进去
                	if(!hashmapIP.containsKey(str[i])) {
                		//把来了的次数加1
                		updateComeTimes(str[i]);
                		
                		//存入hashmap
                		hashmapIP.put(str[i], i);
                	}
                }
                
                
                /*数据处理,搜集MAC地址
                             把学生是否迟到更新为1
//                             一直发一直收clientInputStr*/
//                String finstr="";
//                String regx = "#(.*?)#";
//                Pattern pattern = Pattern.compile(regx);
//                Matcher matcher = pattern.matcher(clientInputStr);
//        		while (matcher.find()) {  
//        			finstr = matcher.group(0);
//        		}  
//                System.out.println("转换后:" + finstr); 
                
                
//                不管是否有这个MAC地址,直接修改
                //updateStudentLate(1,finstr);
                //5/3
               
                
                System.out.println("是的");
//                // 向客户端回复信息    
                DataOutputStream out = new DataOutputStream(socket.getOutputStream());    
                //System.out.print("请输入:\t");    
//                // 发送键盘输入的一行    
                String s = "copy";    
                out.writeUTF(s);    
                  
                out.close();    
                input.close();    
            } catch (Exception e) {    
                System.out.println("服务器 run 异常: " + e.getMessage());    
            } finally {    
                if (socket != null) {    
                    try {    
                        socket.close();    
                    } catch (Exception e) {    
                        socket = null;    
                        System.out.println("服务端 finally 异常:" + e.getMessage());    
                    }    
                }    
            }   
        } 
    }
}
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值