Java 网络编程

1.1、TCP,同步版本的Server:

package com.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * TCP的网络编程,服务器
 * @author Feng
 *
 */
public class TCPTestServer{
	public static void main(String[] args) throws IOException, InterruptedException{
		//服务器开始监听6666号端口
		//从启动上说,必须要先启动服务器端程序
		ServerSocket ss = new ServerSocket(6666);
		//因为服务器需要不断等待连接,所以死循环等待
		while(true){
			System.out.println("等待连接申请中···");
			//接受链接申请,这样写只接受一个连接,这个方法是阻塞式的,如果没有任何连接申请就会一直等待
			Socket s = ss.accept();
			if(s.isConnected()){
				System.out.println("OK!!!!!");
				//使用输入流接受客户端传入的信息
				InputStream stream = s.getInputStream();
				BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
				//注意,像这种输入流的方式属于同步输入,连接成功后如果客户端不传送东西,这里的输入流会一直等待,导致其他连接申请被搁置
				System.out.println(reader.readLine());
			}else{
				System.out.println("NO!!");
			}
		}
	}
}

1.2、TCP,同步版本的Client:

package com.socket;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * TCP网络编程,客户端
 * @author Feng
 *
 */
public class TCPTestClient {
	public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException{
		//客户端申请连接到 127.0.0.1:6666
		//客户端会给这边的socket随机分配端口号,具体是多少并不重要
		Socket s = new Socket("127.0.0.1", 6666);
		//连接成功之后,可以通过管道来进行通话,使用输出管道
		//这里的等待模拟:线连接,但是迟迟不发送信息,这个时候这个链接会被该客户端独占
		Thread.sleep(10000);
		OutputStream stream = s.getOutputStream();
		BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stream));
		writer.write("SHTI!!!!你妹!!!!!");
		writer.flush();
		writer.close();
		s.close();
	}
}


2、TCP,多线程的图片接收服务器

package com.socket;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPJpgGetter {
	public static void main(String[] args) throws IOException{
		ServerSocket ss = new ServerSocket(6666);
		
		while(true){
			Socket s = ss.accept();
			new Thread(new Getter(s)).start();
		}
	}
}

/**
 * 多线程的图片接收类
 * 服务器端开启多个线程用于接收传送过来的图片
 */
class Getter implements Runnable{
	private Socket s = null;
	
	public Getter(Socket s){
		this.s = s;
	}
	@Override
	public void run() {
		try {
			String info = s.getInetAddress().toString();
			
			//从socket读取数据的输入流
			InputStream getter = s.getInputStream();

			//回传数据的输出流
			OutputStream sender = s.getOutputStream();
			
			//为了避免文件名重复的覆盖,使用编号
			int count = 1;
			File temp = new File("D:/" + info + "(" + count + ").jpg");
			while(temp.exists()){
				//这里的处理不是很严谨,还是有可能会导致文件覆盖
				temp = new File("D:/" + info + "(" + (++count) + ").jpg");
			}
			
			System.out.println("接收到来自:" + info + "的传送请求,存储名为:" + temp.getName());
			//创建文件并写入到磁盘的输出流
			FileOutputStream fileWriter = new FileOutputStream(temp);
			
			byte[] buf = new byte[1024];
			int len;
			
			while((len=getter.read(buf)) != -1){
				//写文件的时候要注意写的长度
				fileWriter.write(buf, 0, len);
			}
			
			sender.write("上传成功".getBytes("UTF-8"));
			
			fileWriter.close();
			s.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}



3.1、UDP,同步版本的“Server”:

package com.socket;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**
 * UDP的“服务器”,事实上UDP并没有明确地服务器和客户端的分类,因为是不安全连接,要做的就是确定目标IP和端口号,然后直接发送就好了
 * @author Feng
 *
 */
public class UDPTestServer {
	public static void main(String[] args) throws IOException{
		byte buf[] = new byte[1024];
		//DatagramPacket用来存放需要发送或者要接收的数据
		DatagramPacket dp = new DatagramPacket(buf, buf.length);
		//DatagramSocket就是UDP方式的socket,为服务器指定端口号6666
		DatagramSocket ds = new DatagramSocket(6666);
		while(true){
			//receive方法是阻塞式方法,等待接收数据
			ds.receive(dp);
			//获取发送源的IP地址和端口号,在发送端由于没有指定端口号,这里看到的端口是系统随机分配的端口
			System.out.println("收取到来自 " + dp.getAddress() + ":" + dp.getPort() + " 的信息:");
			//以字符串的形式获取数据并打印
			System.out.println("字符串:" + new String(buf, 0, dp.getLength()));
			
			//接受传送过来的信息,信息已经存储在buf之中
			ByteArrayInputStream in = new ByteArrayInputStream(buf);
			DataInputStream din = new DataInputStream(in);
			System.out.println("数字:" + din.readLong());
			
			System.out.println();
 		}
	}
}


3.2、UDP,同步版本的“Client”:

package com.socket;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class UDPTestClient {
	public static void main(String[] args) throws IOException{
		byte[] buf = new String("你好!~~").getBytes();
		
		//将一个long类型数据转换成byte[];
		long num = 123412341234L;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		DataOutputStream dout = new DataOutputStream(out);
		dout.writeLong(num);
		byte[] buf2 = out.toByteArray();
		System.out.println(buf2.length);
		
		//新建socket的时候如果不指定端口号,那系统将为其默认指定一个地址,作为发送方,这个socket不需要指定端口
		DatagramSocket ds = new DatagramSocket();
		DatagramPacket dp = null;
		
		//DatagramPacket是UDP模式下传输信息的媒介
		//指定目的地址为127.0.0.1:6666
		dp = new DatagramPacket(buf, buf.length, 
				new InetSocketAddress("127.0.0.1", 6666));
		ds.send(dp);
		
		dp = new DatagramPacket(buf2, buf2.length, 
				new InetSocketAddress("127.0.0.1", 6666));
		ds.send(dp);
		
		ds.close();
	}
}


4、UDP聊天小程序

package com.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

/**
 * 两个线程,定义一个接受和一个发送端
 * 写入目标机器的IP地址和端口号即可通信
 * 中文问题:我的MyEclipse默认编码是UTF-8,运行的时候要在Run-Run Configuration-Common-指定GBK,否则会出现中文乱码问题
 * @author Feng
 */
public class UDPTalker {
	
	public static void main(String[] args) throws IOException{
		InetAddress myAdd = InetAddress.getLocalHost();
		System.out.println("本机地址:" + myAdd);
		
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入目标机器IP地址:");
		String ipAdd = reader.readLine();
		
		System.out.println("请输入目标机器端口号:");
		int port = Integer.parseInt(reader.readLine());
		
		DatagramSocket sender = new DatagramSocket();
		DatagramSocket listener = new DatagramSocket(6666);
		
		//消息发送目的地
		InetSocketAddress address = new InetSocketAddress(ipAdd, port);
		
		new Thread(new Send(sender, address)).start();
		new Thread(new Listen(listener)).start();
	}
}

/**
 * 发送线程,接受键盘输入,并将消息发往指定的地址
 * @author Feng
 *
 */
class Send implements Runnable{
	private DatagramSocket ds = null;
	private InetSocketAddress address = null;
	
	public Send(DatagramSocket ds, InetSocketAddress address){
		this.ds = ds;
		this.address = address;
	}
	
	@Override
	public void run() {
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		String line = null;
		
		try {
			while((line=reader.readLine()) != null){
				byte[] temp = line.getBytes("UTF-8");
				//发送数据包,指定了发送的内容以及目的地
				DatagramPacket dp = new DatagramPacket(temp, temp.length, address);
				ds.send(dp);
				
				if("exit".equals(line)){
					break;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

/**
 * 接收线程,等待接收消息并显示
 * @author Feng
 *
 */
class Listen implements Runnable{
	private DatagramSocket ds = null;
	
	public Listen(DatagramSocket ds){
		this.ds = ds;
	}
	
	@Override
	public void run() {
		
		try {
			while(true){
				byte[] temp = new byte[1024];
				//接收数据包,缓存大小为1K
				DatagramPacket dp = new DatagramPacket(temp, temp.length);
				ds.receive(dp);
				
				String address = dp.getAddress().getHostAddress() + "-" + dp.getPort();
				String data = new String(dp.getData(), 0, dp.getLength(), "UTF-8");
				
				System.out.println(address + ": " + data);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值