1.QQ完成

2.使用DatagramSocket实现屏广

Server : //完善代码,区域缩小 2.合包

客户端 : JFrame ,ImageIcon

------------------------------------------------------

项目源码:

package com.it18zhang.udp.screenbroadcast;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.util.HashMap;

import java.util.Map;

import java.util.zip.GZIPInputStream;

/**

 * 客户端接收线程

 */

public class ClientReceiverThread extends Thread {

//存放所有frame的集合

private Map<Long, Map<Integer,FrameUnit>> frames = new HashMap<Long,Map<Integer,FrameUnit>>();

// 客户端窗口

private ClientUI ui;

private DatagramSocket sock;

public ClientReceiverThread(ClientUI ui) {

this.ui = ui;

try {

sock = new DatagramSocket(8889);

}

catch (Exception e) {

}

}

public void run() {

try {

// 缓冲区

byte[] buf = new byte[60 * 1024];

DatagramPacket pack = new DatagramPacket(buf, buf.length);

while (true) {

//接收数据,收到了一帧画面的一个单元。

sock.receive(pack);

FrameUnit unit = new FrameUnit(pack);

//包含gid

Map<Integer,FrameUnit> old = null ;

if(frames.containsKey(unit.getGid())){

//取出原有的

old = frames.get(unit.getGid());

old.put(unit.getIndex(), unit);

}

//不包含

else{

old = new HashMap<Integer,FrameUnit>();

old.put(unit.getIndex(), unit);

frames.put(unit.getGid(),old) ;

}

//是否收集齐全所有的FrameUnit

int count = unit.getCount() ;

int receiveCount = frames.get(unit.getGid()).size();

//齐了

if(count == receiveCount){

byte[] p_w_picpath = mergeImage(old);

ui.refreshImage(p_w_picpath);

}

}

}

catch (Exception e) {

e.printStackTrace();

}

}

/**

* 使用gzip进行解压处理

*/

public byte[] gzipDecompress(byte[] srcdata, int offset, int length) {

try {

ByteArrayOutputStream baos = new ByteArrayOutputStream();

//

ByteArrayInputStream bais = new ByteArrayInputStream(srcdata,offset, length);

GZIPInputStream gzis = new GZIPInputStream(bais);

byte[] buf = new byte[1024];

int len = 0;

while ((len = gzis.read(buf)) != -1) {

baos.write(buf, 0, len);

}

gzis.close();

return baos.toByteArray();

}

catch (Exception e) {

e.printStackTrace();

}

return null;

}

/**

* 合成所有FrameUnit中的rawData,形成byte[]

*/

public byte[] mergeImage(Map<Integer,FrameUnit> units){

try {

ByteArrayOutputStream baos = new ByteArrayOutputStream();

for(int i = 0 ; i < units.size() ; i ++){

FrameUnit u = units.get(i);

baos.write(u.getRawData());

}

return baos.toByteArray() ;

}

catch (Exception e) {

e.printStackTrace();

}

return null ;

}

}

package com.it18zhang.udp.screenbroadcast;

import java.awt.p_w_picpath.BufferedImage;

import javax.swing.ImageIcon;

import javax.swing.JFrame;

import javax.swing.JLabel;

public class ClientUI extends JFrame{

private JLabel label ;

private ImageIcon icon ;

public ClientUI(){

ini();

}

/**

* 初始化

*/

private void ini() {

this.setBounds(0,0, 1366, 768);

this.setLayout(null);

//label

label = new JLabel();

label.setBounds(0, 0, 1366, 768);

label.setLayout(null);

//

icon = new ImageIcon("d:/Koala.jpg");

label.setIcon(icon);

this.add(label);

this.setVisible(true);

this.setDefaultCloseOperation(EXIT_ON_CLOSE);

}

/**

* 刷新图片

*/

public void refreshImage(byte[] data) {

label.setIcon(new ImageIcon(data));

}

}

package com.it18zhang.udp.screenbroadcast;

import java.io.ByteArrayOutputStream;

import java.util.zip.GZIPOutputStream;

import java.util.zip.ZipOutputStream;

/**

 * 数据工具类

 */

public class DataUtil {

/**

* 使用zip算法进行压缩处理

*/

public static byte[] zipCompress(byte[] data) {

try {

//压缩过程

ByteArrayOutputStream baos = new ByteArrayOutputStream();

ZipOutputStream zos = new ZipOutputStream(baos);

zos.write(data);

zos.close();

return baos.toByteArray();

}

catch (Exception e) {

e.printStackTrace();

}

return null ;

}

/**

* 使用gzip算法进行压缩处理

*/

public static byte[] gzipCompress(byte[] data) {

try {

//压缩过程

ByteArrayOutputStream baos = new ByteArrayOutputStream();

GZIPOutputStream gzos = new GZIPOutputStream(baos);

gzos.write(data);

return baos.toByteArray();

}

catch (Exception e) {

e.printStackTrace();

}

return null ;

}

/**

* 将long型数据转换成8个字节

*/

public static byte[] long2Bytes(long l) {

byte[] bytes = new byte[8] ;

bytes[0] = (byte)(l >> 56 );

bytes[1] = (byte)(l >> 48 );

bytes[2] = (byte)(l >> 40 );

bytes[3] = (byte)(l >> 32 );

bytes[4] = (byte)(l >> 24 );

bytes[5] = (byte)(l >> 16 );

bytes[6] = (byte)(l >> 8 );

bytes[7] = (byte)(l >> 0 );

return bytes ;

}

/**

* 将long型数据转换成8个字节

*/

public static long bytes2Long(byte[] bytes) {

long l0 = (bytes[0] & 0xffL) << 56 ;

long l1 = (bytes[1] & 0xffL) << 48 ;

long l2 = (bytes[2] & 0xffL) << 40 ;

long l3 = (bytes[3] & 0xffL) << 32 ;

long l4 = (bytes[4] & 0xffL) << 24 ;

long l5 = (bytes[5] & 0xffL) << 16 ;

long l6 = (bytes[6] & 0xffL) << 8 ;

long l7 = (bytes[7] & 0xffL) << 0 ;

return l0 | l1 | l2 | l3 | l4 | l5 | l6 | l7 ;

}

}

package com.it18zhang.udp.screenbroadcast;

import java.net.DatagramPacket;

/**

 * 一帧画面的每个单元 PackProtocal

 */

public class FrameUnit {

// 组id,时间戳

private long gid;

// 包数量

private int count;

// 包序号

private int index;

// 原始数据

private byte[] rawData;

// 构造

public FrameUnit(DatagramPacket pack) {

parsePack(pack);

}

/**

* 解析包结构

*/

private void parsePack(DatagramPacket pack) {

//

byte[] buf = pack.getData();

int length = pack.getLength();

// 处理有效数据

byte[] validData = new byte[length];

System.arraycopy(buf, 0, validData, 0, length);

// gid

this.gid = DataUtil.bytes2Long(validData);

this.count = validData[8];

this.index = validData[9];

// 有效数据

rawData = new byte[length - 10];

System.arraycopy(validData, 10, rawData, 0, length - 10);

}

public long getGid() {

return gid;

}

public void setGid(long gid) {

this.gid = gid;

}

public int getCount() {

return count;

}

public void setCount(int count) {

this.count = count;

}

public int getIndex() {

return index;

}

public void setIndex(int index) {

this.index = index;

}

public byte[] getRawData() {

return rawData;

}

public void setRawData(byte[] rawData) {

this.rawData = rawData;

}

}

package com.it18zhang.udp.screenbroadcast;

import java.awt.Rectangle;

import java.awt.Robot;

import java.awt.p_w_picpath.BufferedImage;

import java.io.ByteArrayOutputStream;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

import java.util.ArrayList;

import java.util.List;

import javax.p_w_picpathio.ImageIO;

/**

 * 服务器发送

 */

public class ScreenBrocastCastServer {

public static void main(String[] args) throws Exception {

//

DatagramSocket sock = new DatagramSocket(8888);

while(true){

//抓图

byte[] raw = captureScreen();

//创建数据包组

List<DatagramPacket> packs = splitPack(raw,InetAddress.getByName("192.168.12.255") ,8889);

for(DatagramPacket p : packs){

sock.send(p);

}

}

}

/**

* 抓屏

*/

public static byte[] captureScreen(){

try {

//创建屏幕的抓图区域

Rectangle rect = new Rectangle(0, 0, 1024, 768);

BufferedImage p_w_picpath = new Robot().createScreenCapture(rect);

ByteArrayOutputStream baos = new ByteArrayOutputStream();

ImageIO.write(p_w_picpath, "jpg", baos);

byte[] rawData = baos.toByteArray();

return rawData ;

}

catch (Exception e) {

e.printStackTrace();

}

return null ;

}

/**

* 切割原始报文,生成n个pack对象

*/

public static List<DatagramPacket> splitPack(byte[] rawData,InetAddress addr ,int port){

//总长度

int allLen = rawData.length ;

//每个pack的长度

int lenPerPack = 50 * 1024 ;

//pack的个数

int count = 0 ;

if(allLen % lenPerPack == 0 ){

count = allLen / lenPerPack ;

}

else{

count = allLen / lenPerPack  + 1; 

}

//构造小包集合

//组id

long gid = System.nanoTime();

List<DatagramPacket> packs = new ArrayList<DatagramPacket>();

DatagramPacket pack = null ;

for(int i = 0 ; i < count ; i ++){

//

byte[] newPack  = null ;

//是否是最后一个包

if(i != (count - 1)){

//8个字节:时间戳,

//1个字节:包数量 == count

//1个字节:小包的序号==i

newPack = new byte[lenPerPack + 10];

//处理gid

System.arraycopy(DataUtil.long2Bytes(gid), 0, newPack, 0, 8);

//小包数量

newPack[8] = (byte)count ;

//小包序号

newPack[9] = (byte)i ;

//抓图数据

System.arraycopy(rawData, i * lenPerPack, newPack, 10, lenPerPack);

}

//最后一个包

else{

//8个字节:时间戳,

//1个字节:包数量 == count

//1个字节:小包的序号==i

int remain = rawData.length - (count - 1) * lenPerPack ;//剩余长度

newPack = new byte[remain + 10];

//处理gid

System.arraycopy(DataUtil.long2Bytes(gid), 0, newPack, 0, 8);

//小包数量

newPack[8] = (byte)count ;

//小包序号

newPack[9] = (byte)i ;

//抓图数据

System.arraycopy(rawData, i * lenPerPack, newPack, 10, remain);

}

//创建pack

pack = new DatagramPacket(newPack, newPack.length,addr,port);

//添加到集合中

packs.add(pack);

}

return packs ;

}

}

package com.it18zhang.udp.screenbroadcast;

public class StartClient {

public static void main(String[] args) {

ClientUI ui = new ClientUI();

new ClientReceiverThread(ui).start();

}

}

package com.it18zhang.udp;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

public class Receiver {

public static void main(String[] args) throws Exception {

DatagramSocket sock = new DatagramSocket(8889);

while(true){

byte[] buf = new byte[1024];

DatagramPacket pack = new DatagramPacket(buf, 1024);

sock.receive(pack);

//获取接收到的消息长度

int len = pack.getLength();

System.out.println(new String(buf,0,len));

Thread.sleep(500);

}

}

}

package com.it18zhang.udp;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

/**

 * UDP发送器

 */

public class Sender {

public static void main(String[] args) throws Exception {

//8888是数据包套接字端口号,使用该端口向外发送

DatagramSocket sock = new DatagramSocket(8888);

int i = 1 ;

while(true){

//构造数据包套接字对象

//创建缓冲区

byte[] buf = null ;//("helloworld - " + i).getBytes();

buf = new byte[1024 * 60];

//构造数据报包

DatagramPacket pack = new DatagramPacket(buf, buf.length);

//构造发送的地址+port,

//192.168.12.255 ->通配地址,该网段内的所有主机。

InetAddress addr = InetAddress.getByName("192.168.12.255");

pack.setAddress(addr);

pack.setPort(8889);

//通过sock方法数据报包

sock.send(pack);

//编号

i ++ ;

}

}

}

package com.it18zhang.udp;

import com.it18zhang.udp.screenbroadcast.ScreenBrocastCastServer;

public class TestApp {

public static void main(String[] args) {

long l = System.currentTimeMillis();

System.out.println(l);

}

}

**********************************************************************************

学习内容:

java 屏广

遇到问题:

理解屏广意义