`
_kudy
  • 浏览: 15089 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

javase_21(DUp的学习-->*)

 
阅读更多
Socket网络编程

网络协议
IP地址与端口号
本地回路IP: 127.0.0.1
有效端口:0-65535(尽量使用1024个以上-->1024个以上的被占用的概率比较低)
UDP与TCP(协议)
Udp:用户数据包协议,面向无连接,不保证数据的可靠性,不安全,速度快
Tcp:传输数据协议,面向连接,提供可靠无差错的协议,安全,三次握手.

UDP传输:
DatagramSocket 和:DatagramPacket
建立发送端,接收端
建立数据包,
调用Socket的发送接收方法.
关闭Socket
发送端与接收端是两个独立运行的小程序.


发送端:
在发送端,要在数据包对象中明确的IP与端口

DatagramSocket ds =
  new DatagramSocket();
Byte[] by = "hello,net".getBytes();//转换成字节
DatagramPacket dp = new DatagramPacket(by,0,by.length,InerAddress.getByName(127.0.0.1),10000); //数据包打包起来
ds.send(dp);

Ds.close();//关流

接收端:要指定监听的端口
datagramSocket ds = new datagramSocket(10000);
byte [] buf = new byte[1024];
datagramPacket dp = new datagramPacket(buf,by.length);
ds.receive(dp);//把内容接收到dp里面去
String str = new String(dp,getData(),0,dp.length());
System.out.println(str);
ds.close();

UDP聊天程序
通过键盘录入获取要发送的消息.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
br.readLine();
将发送和接收分别封装到两个线程中,main()线程, 和 new Thread()线程


自己写的发送端:
import java.net.DatagramSocket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
class UdpSend
{
	public static void main(String[]args)
	{
		DatagramSocket ds = null;
		try
		{
			ds = new DatagramSocket();
			String line = "I Come as For China";
			byte[]buf = line.getBytes();//转换成字节数组
			DatagramPacket dp = 
					new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),8888);
			ds.send(dp);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}finally
		{
			if(ds!=null)
				ds.close();//关闭流
		}

	}
}

接收端: 当开始监听端口的时候,会出现阻塞,直到监听完毕:
import java.net.DatagramSocket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
class UdpReceive 
{
	public static void main(String[] args) 
	{
		//监听该端口
		DatagramSocket ds = null;
		try
		{
			ds = new DatagramSocket(8888);
			DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
			//它会发生阻塞功能,首先运行这个.他会监听端口 ..
			ds.receive(dp);
			byte[] buf = dp.getData();
			String data = new String(buf,0,dp.getLength());
			System.out.println(data);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}finally
		{
			if(ds!=null)
				ds.close();
		}
		
	}
}

使用了循环的聊天方式:
发送端:()
import java.net.DatagramSocket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.io.BufferedReader;
import java.io.InputStreamReader;
class MySend
{
	public static void main(String[] args) 
	{
		DatagramSocket ds = null;
		BufferedReader br = null;
		try
		{
			ds = new DatagramSocket();
			DatagramPacket dp;
			br = new BufferedReader(new InputStreamReader(System.in));
			System.out.println("聊一下吧~~~");
			while(true)
			{
				String line = br.readLine();
				if("byte".equals(line))break;//如果return;就关闭不了流啦
				byte[] buf = line.getBytes(); //必须要获取到正确的长度
				dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),8888);//封装数据
				ds.send(dp);
			}
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}finally
		{
			try
			{
				if(ds!=null)
					ds.close();
			}finally
			{
				try
				{
					if(br!=null)
						br.close();	
				}catch(IOException e)
				{
					e.printStackTrace();
				}
			}
		}

	}
}

接收端:
import java.net.DatagramSocket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.io.BufferedReader;
import java.io.InputStreamReader;
class MyReceive 
{
	public static void main(String[] args) throws IOException 
	{
		DatagramSocket ds =  new DatagramSocket(8888);//监听端口号
		DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
		while(true)
		{
				ds.receive(dp);//接收数据
				String data = new String(dp.getData(),0,dp.getLength());
				if("byte".equals(data))
						break;
				String ipHost = dp.getAddress().getHostName();//IP主机名字
				String ipName = dp.getAddress().getHostAddress();//IP地址
				int port = dp.getPort();
				System.out.println(ipHost+"("+ipName+")"+" "+port);
				System.out.println(data);
		}
		if(ds!=null)
				ds.close();
	}
}

-->我们需要做到的效果-->多线程实现.实现两边通信..
多线程的效果:
import java.net.DatagramSocket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.InputStreamReader;
class UdpChat 
{
	/*
		利用多线程来实现程序
		Thread-0接收数据
		Main -主线程 发送数据
	*/
	public static void main(String[] args) 
	{
		new Thread(new MyChat()).start();
		DatagramSocket ds = null;
		BufferedReader br = null;
		try
		{
			ds = new DatagramSocket();
			br = new BufferedReader(new InputStreamReader(System.in));
			System.out.println("咱们来聊一下吧~~~");
			while(true)
			{
				String line = br.readLine();
				if(line.equals("byte"))
						break;
				byte[] buf = line.getBytes();//转换成字节数组
				DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),9089);
				ds.send(dp);
			}
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
}

class MyChat implements Runnable
{
	public void run()
	{
		DatagramSocket ds = null;
		try
		{
			ds = new DatagramSocket(9089);
			DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
			while(true)
			{
				ds.receive(dp);//接收数据
				byte[] buf = dp.getData();
				String line = new String(buf,0,dp.getLength());
				String ipStr = dp.getAddress().getHostAddress()+"From:"+dp.getAddress().getHostName();//主机名字
				int port = dp.getPort();
				System.out.println(ipStr+port+" -- ~~"+line);
			}
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}finally
		{
			if(ds!=null)
				ds.close();
		}
	}

}
注意接收数据的时候会出现阻塞-->出现阻塞之后.您多线程怎么跑都运行不了.必须要等我发送端发送数据过去才可以.


获取时间:
			String str = "本地发送于       " + DateFormat.getInstance().format(new Date())
						+ "\r\n" + data + "\r\n";


聊天程序案例分析
一、需求
1.软件的界面:实现窗体Frame、显示文本TextArea或List、发送按钮Button、IP输入TextField
2.聊天功能:实现发送端和接收端程序(多线程)
3.附加功能: 保存聊天记录、关闭软件

二、实现步骤
1.实现软件界面的设计
	1)创建Frame,设置大小、位置、可见 f
	2)创建一个TextArea文本域,用于显示文字 A
	3)创建一个TextArea文本域,用于输入文字 input
	3)创建一个TextField单行输入框用于输入Ip,B
	4)创建一个Button按钮,用于发送信息,C
2.添加事件监听
	1)为f添加窗口监听addWindowListener(WindowAdapter),关闭窗口
	2)为按钮C添加鼠标监听 addMouseListener(MouseAdapter),监听点击事件,发送消息,调用sendMsg
	3)为文本域A添加键盘监听 addKeyListener(KeyAdapter) , 监听按下事件keyPressed发送消息 sendMsg

3.实现发送端 sendMsg方法
	1)创建DatagramSocket对象,绑定闲置端口
	2)获取input中的内容,作为message
	3)获取B中的内容,作为Ip,这里要判断,如果没填,默认指定255.255.255.255
	4)创建DatagramPacket对象,打包数据,统一端口7888
	5)发送数据 ds.send(dp)
	6)将数据和时间显示在A,append方法
4.实现接收端程序
	1)软件已运行就可以收数据了,所以在构造函数中开启新线程,运行接收端 new Thread(new Runnble()).start();
	2)在run方法中实现接收端程序
	3)创建DatagramSocket对象,监听7888端口
	4)准备数据包
	5)接受数据,阻塞,这个要做在循环里面 ds.receive(dp)
	6)获得数据和对方的Ip  , new String(dp.getData(), 0, dp.getLength())\dp.getInetAddress().getHostAddress\(dp.getPort)
	7)获得当前时间, DateFormat.getInstance().format(new Date());
	8)将数据显示在A,append方法
	


import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.FileWriter;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.text.DateFormat;
import java.util.Date;

class MyChatTest 
{
	public static void main(String[] args) 
	{
		MyChatOne mc = new MyChatOne();
	}
}

class MyChatOne
{
	private Frame f;
	private TextArea disPlay,dataInput;
	private TextField ipInput;//IP地址的读取(单行文本可编程的组件)
	private Button senBtn;
	private boolean close = false;
	public MyChatOne()
	{
		f = new Frame();
		f.setSize(370,500);
		f.setLocation(100,150);
		f.setResizable(false);//不可移动
		disPlay = new TextArea(23,30);
		disPlay.setEditable(false);//不可编辑
		dataInput = new TextArea(10,30);
		ipInput = new TextField(20);
		senBtn = new Button("发送(Ctrl+Enter)");
		
		f.add(disPlay,"North");
		f.add(dataInput,"Center");
		Panel p = new Panel(new BorderLayout());
		p.add(ipInput,"West");//西边
		p.add(senBtn,"East");//北'
		f.add(p,"South");//南
		f.setVisible(true);
		handEvent();
		new Thread(new ReceiveInMyChat()).start();
	}

	//监听
	private void handEvent()
	{
		f.addWindowListener(new WindowAdapter(){
		public void windowClosing(WindowEvent e)
		{
			e.getWindow().dispose();
			close = true;
			ipInput.setText("127.0.0.1");//阻塞,随便运行一下发送端就可以.
		}
		});
		senBtn.addMouseListener(new MouseAdapter(){
		public void mouseClicked(MouseEvent e)
		{
			sendMsg();//当您触发我的确定按钮.我需要做的事情..
		}
		});
		dataInput.addKeyListener(new KeyAdapter(){
		//监听编辑器.当按下键盘并且+回车..你懂的..
		public void keyPressed(KeyEvent e)
			{
				if(e.isControlDown()&&e.getKeyChar()=='\n')
					sendMsg();
			}
		});
			

	}

	private void sendMsg()
	{
		//实现发送端的程序
		DatagramSocket ds = null;
		try
		{
			ds = new DatagramSocket();
			String data = dataInput.getText();//获取里面的数据
			String ip = ipInput.getText();//获取单行编辑条的内容
			if(ip.length()==0)
			{
				ip = "127.0.0.1";
				ipInput.setText(ip);//如果没有.我也必须往里面写入数据
			}
			byte[] buf = data.getBytes();//获取字节数组

			//封包
			DatagramPacket dp = 
					new DatagramPacket(buf,buf.length,InetAddress.getByName(ip),8888);//封装数据
			//发包
			ds.send(dp);
			//将信息显示在display()这边
			String str = "本地发送于       " + DateFormat.getInstance().format(new Date())
						+ "\r\n" + data + "\r\n";
			disPlay.append(str);//追加内容到这边来
			dataInput.setText("");//表示清空内容~
			saveMessage(str);
			//等一下我们可以做一下聊天记录
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}finally
		{
			if(ds!=null)
				ds.close();
		}
	}

		//接收端咱们用多线程实现
	class ReceiveInMyChat implements Runnable
	{
		@Override
		public void run()
		{
			DatagramSocket ds = null;
			try
			{
				ds = new DatagramSocket(8888);//指定需要监听的端口号
				DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
				while(true)
				{
					//阻塞-->必须要执行内容才可以到这一步.但我们到这一步.可以把多线程退出.
					ds.receive(dp);
					if(close)
							break;//跳出循环.多线程就会关闭	
					String data = new String(dp.getData(),0,dp.getLength());
					String ip = dp.getAddress().getHostAddress()+"("+dp.getAddress().getHostName()+")";
					String str = ip + "  发送于  " + DateFormat.getInstance().format(new Date())
									+ "\r\n" + data + "\r\n";
					disPlay.append(str);
					saveMessage(str);
				}
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}finally
			{
				if(ds!=null)
					ds.close();
			}
		}
	}

	
	/*
		聊天记录的保存:	
	*/
	private void saveMessage(String str)
	{
		FileWriter fw = null;
		try
		{
			fw = new FileWriter("d:/聊天记录.txt",true);//表示从后面追加
			fw.write(str);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		finally
		{
			try
			{
				if(fw!=null)
					fw.close();//关流.
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
	}
}


多线程的回顾:
package com.javami.kudyDemo.udpStudy;

public class ThreadDemo {

	/**
	 * 主要内容复习下多线程的回归,..主线程必须执行先~~
	 */
	public static void main(String[] args) {
		new Thread(new MyThread()).start();
		for(int i=0; i<10; i++)
		{
			System.out.println("主线程!!!");
		}
	}

}

class MyThread implements Runnable
{
	public void run()
	{
		int num = 0;
		while(true)
		{
			System.out.println("To Learn How");
			num ++;
			if(num>10)
					break;
		}
	}
}


心得与总结:

多线程需要复习-->
首先在接收数据的时候.会遇到阻塞-->必须要运行一下发送端程序..
时间这个类也得复习..
明天早上起来的任务-->必须要回顾知识..和敲写多一次这个程序.
今天的时间掌握得还是比较不好的~~希望下次好好努力改正..需要认真去对待每一件事..
多背下单词.

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics