java网络编程

UDP(聊天主要,聊天数据丢不丢无所谓,主要速度快,网络视频回忆)

    将数据及源和目的封装成包,不需要简历连接   面向无链接

    每个数据报的大小限制在64k 

    因为无连接,是不可靠协议

   不需要建立连接速度快


TCP

   建立连接,形成传输通道

   在连接中进行大数据传输

   通过三次握手完成连接,是可靠协议

  必须建立连接,效率稍低

对方必须在,对方必须在,再放松消息。对方在不在,三次握手形式。


Socket 

  socket 就是为网络服务提供的一种机制

  通信的俩端都有socket

  网络通信其实就是Socket 间的通信

  数据在两个socket 间通过IO传输

UDP 传输

     DatagramSocket 与DatagramPacket

    建立发送端,接收端

    建立数据包

    调用Socket 的发送接收方法

    关闭Socket

    发送端与接收端是两个独立的运行程序

简单的udp 接收端和发送端

接收端:

package com.zkk;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class UDPReceiver {

	//需求 定义一个应用程序, 用于接收udp 传输的数据并处理的。
	//思路   在定义接收端的时候,通常会监听一个端口,其实就是给这个接收网络应用程序定义数字标识
	    //方便于明确哪些数据过来应用程序可以处理
	//1 定义udpSocket 服务
	//2 定义数据包 因为要存储接收到的字节数据,因为数据包对象中有更多可以提取字节数据中不同数据信息
	//3 通过socket 服务的receiver 方法将收到的数据存入意定义好的数据包中
	//4 通过数据包对象的特有功能, 将这些不同的数据取出,打印在控制台上
	//5 关闭资源
	public static void main(String[] args) {
		//创建udp socket 建立端点
        try {
			DatagramSocket ds=new DatagramSocket(10000);
            //定义数据包 用于存储数据
			byte[] buf=new byte[1024];
			DatagramPacket dp=new DatagramPacket(buf, buf.length);
			//3 通过服务的receiver 方法将接收到的数据存入数据包中
			ds.receive(dp);
			//通过数据包方法获取其中数据
			String ip=dp.getAddress().getHostAddress();
			String data=new String(dp.getData(),0,dp.getLength());
			int port=dp.getPort();
			System.out.println("ip:"+ip);
			System.out.println("data:"+data);
			System.out.println("port:"+port);
					
        } catch (Exception e) {
			e.printStackTrace();
		}
	}

}

发送端

package com.zkk;

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

public class UdpSend {

	/**
	 * 需求:通过udp 传输方式,将一段文字数据发送出去 1,建立udpsocket 服务 2,要提供数据,数据封装到数据包中 3,通过Socket
	 * 服务发送功能,将数据包发出去 4, 关闭资源
	 */
	public static void main(String[] args) {

		try {
			// 1,建立udpsocket 服务
			DatagramSocket ds = new DatagramSocket(9999);
			byte[] data = "udp ge men lai le".getBytes();
			// 2,要提供数据,数据封装到数据包中
			DatagramPacket dp = new DatagramPacket(data, data.length,
					InetAddress.getByName("192.168.1.102"), 10000);
          //3 3,通过Socket  服务发送功能,将数据包发出去
		     ds.send(dp);
			
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}catch (IOException e) {
			e.printStackTrace();
		}
	}

}


广播地址:192.168.1.0  网络段192.168.1.255  这个网络段里面广播地址  

键盘录入的发送端

   

package com.zkk;

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.SocketException;
import java.net.UnknownHostException;

public class UdpSend {

	/**
	 * 需求:通过udp 传输方式,将一段文字数据发送出去 1,建立udpsocket 服务 2,要提供数据,数据封装到数据包中 3,通过Socket
	 * 服务发送功能,将数据包发出去 4, 关闭资源
	 */
	public static void main(String[] args) {

		try {
			// 1,建立udpsocket 服务
			DatagramSocket ds = new DatagramSocket(9999);
			BufferedReader bufer = new BufferedReader(new InputStreamReader(
					System.in));
			String line = null;
			while ((line = bufer.readLine()) != null) {
				if ("886".equals(line)) {
					break;
				}
				byte[] buf = line.getBytes();
				//广播地址:192.168.1.0  网络段192.168.1.255  这个网络段里面广播地址   一下地址写255 也行
				DatagramPacket dp = new DatagramPacket(buf, buf.length,
						InetAddress.getByName("192.168.1.102"), 10000);
				// 3 3,通过Socket 服务发送功能,将数据包发出去
				ds.send(dp);
			}
			ds.close();

		} catch (SocketException e) {
			e.printStackTrace();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

键盘录入的接收段

package com.zkk;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class UDPReceiver {

	//需求 定义一个应用程序, 用于接收udp 传输的数据并处理的。
	//思路   在定义接收端的时候,通常会监听一个端口,其实就是给这个接收网络应用程序定义数字标识
	    //方便于明确哪些数据过来应用程序可以处理
	//1 定义udpSocket 服务
	//2 定义数据包 因为要存储接收到的字节数据,因为数据包对象中有更多可以提取字节数据中不同数据信息
	//3 通过socket 服务的receiver 方法将收到的数据存入意定义好的数据包中
	//4 通过数据包对象的特有功能, 将这些不同的数据取出,打印在控制台上
	//5 关闭资源
	public static void main(String[] args) {
		//创建udp socket 建立端点
        try {
			DatagramSocket ds=new DatagramSocket(10000);
			while(true){
				byte[] buf=new byte[1024];
				DatagramPacket dp=new DatagramPacket(buf, buf.length);
				//3 通过服务的receiver 方法将接收到的数据存入数据包中
				ds.receive(dp);
				//通过数据包方法获取其中数据
				String ip=dp.getAddress().getHostAddress();
				String data=new String(dp.getData(),0,dp.getLength());
				int port=dp.getPort();
				System.out.println("ip:"+ip);
				System.out.println("data:"+data);
				System.out.println("port:"+port);
			}
            //定义数据包 用于存储数据
			//接收端通常不关
        } catch (Exception e) {
			e.printStackTrace();
		}
	}

}


多线程聊天

package com.zkk;

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.SocketException;

public class ChatDemo {

	/**
	 * 编写一个聊天程序 有收数据的部分,和发数据的部分 这两部分需要同时执行 那就用到多线程技术 一个线程控制收,一个线程控制发
	 * 
	 * 因为收和发动作是不一致的,所以要定义两个run方法 而且这两个方法要封装到不同类中。
	 */
	public static void main(String[] args) {
		new ChatDemo().init();

	}

	private void init() {
		try {
			DatagramSocket sendSocket = new DatagramSocket();
			DatagramSocket receSocket = new DatagramSocket(10000);
			new Thread(new Send(sendSocket)).start();
			new Thread(new Rece(receSocket)).start();
		} catch (Exception e) {
			e.printStackTrace();
		}// 发送端

	}

	class Send implements Runnable {
		private DatagramSocket ds;

		public Send(DatagramSocket ds) {
			this.ds = ds;
		}

		@Override
		public void run() {
			BufferedReader bufr = new BufferedReader(new InputStreamReader(
					System.in));
			String line = null;
			try {
				while ((line = bufr.readLine()) != null) {
					if ("886".equals(line)) {
						break;
					}
					byte[] buf = line.getBytes();
					DatagramPacket dp = new DatagramPacket(buf, buf.length,
							InetAddress.getByName("192.168.1.102"), 10000);
					ds.send(dp);

				}
			} catch (Exception e) {
				throw new RuntimeException("发送失败:");
			}
		}

	}

	class Rece implements Runnable {
		private DatagramSocket ds;

		public Rece(DatagramSocket ds) {
			this.ds = ds;
		}

		@Override
		public void run() {
			try {
				while (true) {
					byte[] buf = new byte[1024];
					DatagramPacket dp = new DatagramPacket(buf, buf.length);
					ds.receive(dp);
					String ip = dp.getAddress().getHostAddress();
					String data = new String(dp.getData(), 0, dp.getLength());
					System.out.println("ip:" + ip + "data:" + data);
				}
			} catch (Exception ex) {
				throw new RuntimeException("接收失败");
			}
		}

	}

}



TCP 传输

  Socket 和 ServerSocket

   建立客户端和服务端

   建立连接后,通过Socket 中的io流进行数据的传输

   关闭socket 

  同样客户端与服务器是俩个独立的应用程序

   客户端想服务端发送简单数据示例:

   客户端:

    

package com.zkk;

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

public class TcpClient {

/**
 * 客户端
 * 通过查阅socket 对象,发现在该对象建立时,就可以去连接指定主机
 * 因为tcp 是面向连接的,所以在建立socket 服务时,就要有服务端存在,并连接成功,形成同路后,在该通道进行数据的传输
 *需求:
 * 给服务端发送一个文本数据
 * 步骤
 * 1,创建socket 服务,并指定要连接的主机和端口
 */
	public static void main(String[] args) {
         try {
        	 // 1,创建socket 服务,并指定要连接的主机和端口
			Socket clientSocket=new Socket("192.168.1.102", 10002);
			//为了发送数据,应该获取socket 流中的输出流
			OutputStream outputStream = clientSocket.getOutputStream();
			outputStream.write("tcp ge men lai le ".getBytes());
			clientSocket.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

服务端

package com.zkk;

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

public class TcpServer {

	/**
	 * 需求: 定义端点接收数据并打印在控制台上 服务端: 1,建立服务端的socket serverSocket(); 并监听一个端口
	 * 2,获取连接过来的客户端对象 通过serverSocket 的accept 方法。 没有连接就会等,所以这个方法阻塞式
	 * 3,客户端如果如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该对象的读取流来读取发过来的数据
	 * 
	 * 4,关闭服务端(可选)
	 */
	public static void main(String[] args) {

		try {
			// 建立服务端的socket 并监听端口
			ServerSocket serverSocket = new ServerSocket(10002);
			// 通过accept 方法获取连接过来的客户端对象
			Socket socket = serverSocket.accept();
			String ip = socket.getInetAddress().getHostAddress();
			System.out.println(ip + "..connected");
			// 获取客户端发送过来的数据,那么使用客户端对象的读取流来读取数据
			InputStream inputStream = socket.getInputStream();
			byte[] buf = new byte[1024];
			int len = inputStream.read(buf);

			System.out.println(new String(buf, 0, len));
			socket.close();// 这里是关闭客户端
		} catch (IOException e) {
		}
	}

}

tcp 服务端反馈客户端

   客户端

   

package com.zkk;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class TcpClient {

	/**
	 * 演示 tcp 的传输的客户端和服务端的互访 需求: 客户端给服务端发送数据,服务端收到后,给客户端反馈信息 1。建立socket
	 * 服务,指定要连接主机和端口 2 socket 流中的输出流,将数据写到流中,通过网络发送给服务端 3 获取socket
	 * 流中的输入流,将服务端反馈的数据获取到,并打印
	 */
	public static void main(String[] args) {
		try {
			// 1,创建socket 服务,并指定要连接的主机和端口
			Socket clientSocket = new Socket("192.168.1.102", 10002);
			// 为了发送数据,应该获取socket 流中的输出流
			OutputStream outputStream = clientSocket.getOutputStream();
			outputStream.write("服务端你好,我是客户端".getBytes());
			InputStream in=clientSocket.getInputStream();
			byte[] buf=new byte[1024];
			int len = in.read(buf);
			System.out.println(new String(buf,0,len));
			clientSocket.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}


服务端

package com.zkk;

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

public class TcpServer {

	/**
	 * 需求: 定义端点接收数据并打印在控制台上 服务端: 1,建立服务端的socket serverSocket(); 并监听一个端口
	 * 2,获取连接过来的客户端对象 通过serverSocket 的accept 方法。 没有连接就会等,所以这个方法阻塞式
	 * 3,客户端如果如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该对象的读取流来读取发过来的数据
	 * 
	 * 4,关闭服务端(可选)
	 */
	public static void main(String[] args) {

		try {
			// 建立服务端的socket 并监听端口
			ServerSocket serverSocket = new ServerSocket(10002);
			// 通过accept 方法获取连接过来的客户端对象
			Socket clientSocket = serverSocket.accept();
			String ip = clientSocket.getInetAddress().getHostAddress();
			System.out.println(ip + "..connected");
			// 获取客户端发送过来的数据,那么使用客户端对象的读取流来读取数据
			InputStream inputStream = clientSocket.getInputStream();
			byte[] buf = new byte[1024];
			int len = inputStream.read(buf);

			System.out.println(new String(buf, 0, len));
			OutputStream outputStream = clientSocket.getOutputStream();
			Thread.sleep(10000);
			outputStream.write("我是服务器,你也好。。".getBytes());
			clientSocket.close();// 这里是关闭客户端
		} catch (Exception e) {
		}
	}

}


客户端字符串键盘录入 服务器返回大写

  客户端:

  

package com.zkk;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class TcpClient {

	/**
	 * 文本转换服务器 客户端给服务器发送文本,服务器会将文本转成大写再返回给客户端 而且客户端可以不断的进行文本转换,当客户端输入over 时,转换结束
	 * 分析:
	 * 客户端
	 *    既然是操作设备上的数据,那么就可以使用io技术,并按照io的操作规律来思考
	 *    源:键盘录入
	 *    目的:网路设备,网络输出流
	 *    而且操作的是文本数据,可以选择字符流
	 *    步骤:
	 *     1,建立服务
	 *     2,获取键盘录入
	 *     3,将数据发送给服务端
	 *     4,后去服务端返回饿大写数据
	 *     5结束,管资源
	 *     都是文本可以使用字符流进行操作,同时提高效率,加入缓冲
	 */
	public static void main(String[] args) {
		try {
			// 1,创建socket 服务,并指定要连接的主机和端口
			Socket clientSocket = new Socket("192.168.1.102", 10002);
			//定义读取键盘数据的流对象
			BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
			//定义目地,将数据写入到socket 输出流。发给服务端
		//	BufferedWriter bufOut=new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
			PrintWriter out=new PrintWriter(clientSocket.getOutputStream(),true);
			//定义一个socket 读取流,读取服务端返回的大写信息
			BufferedReader bufin=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
			String line=null;
			while((line=bufr.readLine())!=null){
				
				if("over".equals(line)){
					break;
				}
				out.println(line.toUpperCase());
				/*bufOut.write(line);//这个数据写到缓冲区中了,必须刷新  这里没有回车符号,把回车符号之前的数据发送到服务端了。服务端是readLine()并没有返回数据
				bufOut.newLine();
				bufOut.flush();*/
				String readLine = bufin.readLine();
				System.out.println("server:"+readLine);
			}
			bufr.close();
			clientSocket.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}
/**
 * 该例子出现的问题
 *   现象:客户端和服务端都在莫名的等待
 *   为什么?
 *   因为客户端和服务端都有阻塞方法,这些方法没有读取到结束标记,那么就一直等 而导致两端都在等
 * 
 * */

服务端

package com.zkk;

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

/**
 * 服务端
 * 
 * @author Administrator 源:socket 读取流 目的:socket 输出流 都是文本
 */
public class TcpServer {
	public static void main(String[] args) {

		try {
			// 建立服务端的socket 并监听端口
			ServerSocket serverSocket = new ServerSocket(10002);
			Socket clientSocket = serverSocket.accept();
			String ip = clientSocket.getInetAddress().getHostAddress();
			System.out.println(ip + "...connect");
			// 读取socket 读取流这哦功能的数据
			BufferedReader bufIn = new BufferedReader(new InputStreamReader(
					clientSocket.getInputStream()));
			// 目的 socket 输出流 将大写数据写入socket 输出流,并发生哦功能给客户端
			BufferedWriter bufout = new BufferedWriter(new OutputStreamWriter(
					clientSocket.getOutputStream()));
			String line = null;
			while ((line = bufIn.readLine()) != null) {
				bufout.write(line.toUpperCase());
				bufout.newLine();
				bufout.flush();
			}
			clientSocket.close();
		} catch (Exception e) {
		}
	}

}

tcp 上传文本文件

客户端

package com.zkk;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class TcpClient {

	public static void main(String[] args) {
		try {
			// 1,创建socket 服务,并指定要连接的主机和端口
			Socket clientSocket = new Socket("192.168.1.101", 10002);
			BufferedReader bufr=new BufferedReader(new FileReader("c://1.txt"));
			PrintWriter out=new PrintWriter(clientSocket.getOutputStream(),true);
			String line=null;
			while((line=bufr.readLine())!=null){
				out.println(line);
				System.out.println(line);
			}
			clientSocket.shutdownOutput();//关闭客户端的输出流,相当于给流中加入一个结束标记
			BufferedReader bufin=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
			String string = bufin.readLine();
			System.out.println(string);
			bufr.close();
			clientSocket.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}


服务端:

package com.zkk;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服务端
 * 
 * @author Administrator 源:socket 读取流 目的:socket 输出流 都是文本
 */
public class TcpServer {
	public static void main(String[] args) {

		try {
			// 建立服务端的socket 并监听端口
			ServerSocket serverSocket = new ServerSocket(10002);
			Socket clientSocket = serverSocket.accept();
			String ip = clientSocket.getInetAddress().getHostAddress();
			System.out.println(ip + "...connect");
			// 读取socket 读取流这哦功能的数据
			BufferedReader bufIn = new BufferedReader(new InputStreamReader(
					clientSocket.getInputStream()));
			
			PrintWriter out=new PrintWriter(new FileWriter("c://2.txt"),true);
			String line=null;
			while((line=bufIn.readLine())!=null){
				out.println(line);
			}
			PrintWriter pw=new PrintWriter(clientSocket.getOutputStream(),true); 
			pw.println("上传成功");
			/*BufferedWriter bufout = new BufferedWriter(new OutputStreamWriter(
					clientSocket.getOutputStream()));
			String line = null;
			while ((line = bufIn.readLine()) != null) {
				bufout.write(line.toUpperCase());
				bufout.newLine();
				Thread.sleep(10000);
				bufout.flush();
			}*/
			/*bufIn.close();
			pw.close();*/
			out.close();
			clientSocket.close();
			serverSocket.close();
		} catch (Exception e) {
		}
	}

}

 

tcp 上传图片

    客户端

   

package com.zkk;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class TcpClient {
/**
 * 客户端:
 *  1,服务端点
 *  2,读取客户端已经有的图片
 *  3 通过socket 输出流将数据发给服务端
 *  4读取服务器端反馈的信息
 *  5关闭
 * @param args
 */
	public static void main(String[] args) {
		try {
			// 1,创建socket 服务,并指定要连接的主机和端口
			Socket clientSocket = new Socket("192.168.1.101", 10002);
			FileInputStream fis=new FileInputStream("c://aa.jpg");
			OutputStream outputStream = clientSocket.getOutputStream();
			byte [] buf=new byte[1024];
			int len=0;
			while((len=fis.read(buf))!=-1){
				outputStream.write(buf, 0, len);
			}
			//告诉服务端 数据已经写完
			clientSocket.shutdownOutput();
			InputStream in=clientSocket.getInputStream();
			byte[] bufin=new byte[1024];
			int num=in.read(bufin);
			System.out.println(new String(bufin,0,num));
			fis.close();
			clientSocket.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}

服务端

  

package com.zkk;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服务端
 * 
 * 
 */
public class TcpServer {
	public static void main(String[] args) {

		try {
			// 建立服务端的socket 并监听端口
			ServerSocket serverSocket = new ServerSocket(10002);
			Socket clientSocket = serverSocket.accept();
			String ip = clientSocket.getInetAddress().getHostAddress();
			System.out.println(ip + "...connect");
			// 读取socket 读取流这哦功能的数据
			InputStream inputStream = clientSocket.getInputStream();
			FileOutputStream fos=new FileOutputStream("c://bb.jpg");
			byte[] buffer=new byte[1024];
			int len=0;
			while((len=inputStream.read(buffer))!=-1){
				fos.write(buffer, 0, len);
			}
			OutputStream outputStream = clientSocket.getOutputStream();
			outputStream.write("上传成功".getBytes());
			fos.close();
			clientSocket.close();
		} catch (Exception e) {
		}
	}

}

这个服务端有个局限性,当a客户端连接上后。被服务端获取到,服务端执行具体流程,这时b客户端连接,只有等待.

这时b客户端连接,只有等待

因为服务端还没有处理完a客户端的请求,还有循环回来执行下次accept方法,所以暂时获取不到b客户端对象

那么服务端最后就是将每个客户端封装到一个单独的线程中,这样,就可以同时处理多个客户端的请求

如何定义线程呢?

只要明确了每一个客户端要在服务端执行的代码,将该代码存入run方法中。

多线程tcp上传图片

 客户端:

package com.zkk;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class TcpClient {
/**
 * 客户端:
 *  1,服务端点
 *  2,读取客户端已经有的图片
 *  3 通过socket 输出流将数据发给服务端
 *  4读取服务器端反馈的信息
 *  5关闭
 * @param args
 */
	public static void main(String[] args) {
		try {
			// 1,创建socket 服务,并指定要连接的主机和端口
			Socket clientSocket = new Socket("192.168.1.101", 10002);
			FileInputStream fis=new FileInputStream("c://aa.jpg");
			OutputStream outputStream = clientSocket.getOutputStream();
			byte [] buf=new byte[1024];
			int len=0;
			while((len=fis.read(buf))!=-1){
				outputStream.write(buf, 0, len);
			}
			//告诉服务端 数据已经写完
			clientSocket.shutdownOutput();
			InputStream in=clientSocket.getInputStream();
			byte[] bufin=new byte[1024];
			int num=in.read(bufin);
			System.out.println(new String(bufin,0,num));
			fis.close();
			clientSocket.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}

  

服务端:

 

package com.zkk;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服务端
 * 
 * 
 */
public class TcpServer {
	public static void main(String[] args) {
		new TcpServer().init();
	}

	private void init() {
		try {
			// 建立服务端的socket 并监听端口
			ServerSocket serverSocket = new ServerSocket(10002);
			Socket clientSocket = serverSocket.accept();
			new Thread(new PicThread(clientSocket)).start();

		} catch (Exception e) {
		}

	}

	class PicThread implements Runnable {
		private Socket clientSocket;

		public PicThread(Socket s) {
			this.clientSocket = s;
		}

		@Override
		public void run() {
			try {
				String ip = clientSocket.getInetAddress().getHostAddress();
				System.out.println(ip + "...connect");
				// 读取socket 读取流这哦功能的数据
				InputStream inputStream = clientSocket.getInputStream();
				FileOutputStream fos = new FileOutputStream("c://"+ip+"_"+System.currentTimeMillis()+".jpg");
				byte[] buffer = new byte[1024];
				int len = 0;
				while ((len = inputStream.read(buffer)) != -1) {
					fos.write(buffer, 0, len);
				}
				OutputStream outputStream = clientSocket.getOutputStream();
				outputStream.write("上传成功".getBytes());
				fos.close();
				clientSocket.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}
}

客户端并发登录

客户端:

package com.zkk;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class TcpClient {
	/**
	 * 并发登录
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			// 1,创建socket 服务,并指定要连接的主机和端口
			Socket clientSocket = new Socket("192.168.1.102", 10003);
			BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
			PrintWriter out=new PrintWriter(clientSocket.getOutputStream(),true);
			BufferedReader bufin=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
			for(int x=0;x<3;x++){
				String line=bufr.readLine();
				if(null==line){
					break;
				}
				out.println(line);
				String info=bufin.readLine();
				System.out.println("info:"+info);
				if(info.contains("欢迎")){
					break;
				}
			}
			bufr.close();
			clientSocket.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
}

服务端

package com.zkk;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class LoginServer {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new LoginServer().init();
	}

	private void init() {
		try {
			ServerSocket ss = new ServerSocket(10003);
			while (true) {
				Socket s = ss.accept();
				new Thread(new UserThread(s)).start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	class UserThread implements Runnable {
		private Socket ss;

		public UserThread(Socket ss) {
			this.ss = ss;
		}

		@Override
		public void run() {
			String ip = ss.getInetAddress().getHostAddress();
			System.out.println(ip + "...connected");
			for (int i = 0; i < 3; i++) {

				try {
					BufferedReader bufin = new BufferedReader(
							new InputStreamReader(ss.getInputStream()));
					String name = bufin.readLine();
					if (null == name) {
						break;
					}
					BufferedReader bufr = new BufferedReader(new FileReader(
							"c://user.txt"));
					PrintWriter out = new PrintWriter(ss.getOutputStream(),
							true);
					String line = null;
					boolean flag = false;
					while ((line = bufr.readLine()) != null) {
						if (line.equals(name)) {
							flag = true;
							break;
						}
					}
					if (flag) {
						System.out.println(name + ",已登陆");
						out.println(name + ",欢迎光临");
						break;
					} else {
						System.out.println(name + ",尝试登录");
						out.println(name + ",用户名不存在");
					}

				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			try {
				ss.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

}






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值