网络编程

TCP编程

TCP Transmission Control Protocol 传输控制协议,是一种面向连接(两端之间想要数据传输,必须先建立一个持久性的通道)的、可靠(数据不能有丢包的现象)的、基于字节流的传输层通信协议,主要有两个端:1,客户端(Client),主动发出连接的请求2,服务端(Server):被动接受接受客户端的请求,并相应客户端

TCP三次握手

   案例1:客户端<------>服务端

需求:客户端键盘录入,服务端输出到控制台

具体实现步骤:

server端

1,建立TCP服务端并且绑定端口,监听端口传来的请求    

 ServerSocket server =new ServerSocket(10089);

3,通过Server获取一个来自客户端的请求,建立了TCP连接,一个客户端只能有一个Socket

Socket socket =server.accept();//程序阻塞,用于监听客户端的请求

5,读取客户端传来的数据,服务端获取客户端传来的数据流(字节流需要转化为字符流),

  BufferedReader br =new BufferedReader(new InputStreamReader(socket.getInputStream()));

6,从客户端读取数据

 String line = null;
      while((line = br.readLine())!=null) {
          System.out.println(line);         
      }

10, socket.close();//因为这个socket包含了br所以关掉了socket就是关掉了br

client端

2, 创建一个TCP客户端,指定目标IP地址及端口号,已经连上了服务端

Socket client =new Socket("192.168.1.2",10089);

4,客户端向服务端传输的输出流client.getOutputStream()

BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));

7,从客户端的控制台读取数据

BufferedReader br =new BufferedReader(new InputStreamReader(System.in));

8,从控制台读取数据,只要不是"888"就一直读取

String line = null;
    while(!(line = br.readLine()).equals("888")) {
        bw.write(line);//通过输出流传给服务器
        bw.newLine();
        bw.flush();
    }

9,关流

   client.close();
    br.close(); 

package TCP;

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

public class TCPClient01 {

	public static void main(String[] args) throws UnknownHostException, IOException {
		// TODO Auto-generated method stub
     //1,创建一个TCP客户端,指定目标IP地址及端口号,已经连上了服务端
		Socket client =new Socket("192.168.1.2",10089);
	//客户端获取服务端的输入流client.getInputStream()
	//客户端向服务端传输的输出流client.getOutputStream()
	BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
	//2,从客户端的控制台读取数据
	BufferedReader br =new BufferedReader(new InputStreamReader(System.in));

	//3,从控制台读取数据,只要不是"888"就一直读取
	String line = null;
	while(!(line = br.readLine()).equals("888")) {
		bw.write(line);//通过输出流传给服务器
		bw.newLine();
		bw.flush();
	}
	//关流
	client.close();
	br.close();
	}

}
package TCP;

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

public class TCPServer01 {
/**
 * 需求:客户端键盘录入,服务端输出到控制台
 * @throws IOException 
 * 
 */
	public static void main(String[] args) throws IOException {
	//1,建立TCP服务端并且绑定端口,监听端口传来的请求	
      ServerSocket server =new ServerSocket(10089);
      System.out.println("服务端开启.........");
    //2,通过Server获取一个来自客户端的请求,建立了TCP连接,一个客户端只能有一个Socket
      Socket socket =server.accept();//程序阻塞,用于监听客户端的请求
      System.out.println("server:获取一个客户端请求(链接)。。。。");  
    //3,读取客户端传来的数据
    //服务端获取客户端传来的数据流(字节流需要转化为字符流)socket.getInputStream()
      BufferedReader br =new BufferedReader(new InputStreamReader(socket.getInputStream()));
    //4,从客户端读取数据
      String line = null;
      while((line = br.readLine())!=null) {
    	  System.out.println(line);   	  
      }
      socket.close();//因为这个socket包含了br所以关掉了socket就是关掉了br
	}

}

   案例2:

需求:从客户端上传文件给服务端

先画下流的流向图

 

注意上面的箭头不代表方向,只是代表一个通道而已,这个通道是双向的,如果出现两个通道就要关掉其中一个

代码

public class TCPServer02 {

	public static void main(String[] args) throws IOException {
   //1,建立TCP服务并且绑定端口,监听端口传来的请求		
   ServerSocket  server =new ServerSocket(5678);
   System.out.println("Server:服务器开启。。。。");
   //2,通过server获取一个来自客户端的请求,建立TCP的连接
   Socket socket =server.accept();
   System.out.println("Server:接受一个连接。。。。");
   //3,读取客户端传来的数据,服务端获取客户端传来的数据流(字节流需要转化为字符流),
   BufferedReader br =new BufferedReader(new InputStreamReader(socket.getInputStream()));
   //4,获取文件的输出流
   BufferedWriter  b =new BufferedWriter(new FileWriter("copytest.txt")); 
 //5,获取服务端的输出流,向客户端做一个回应
   BufferedWriter bb =new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
   String line =null;
     //4,从客户端读取数据
     while((line =br.readLine())!=null) {
    	 b.write(line);
    	 b.newLine();
    	 b.flush();
     }  
     System.out.println("文件上传成功,服务器关闭。。。。");  
     //关闭server输入流,服务端和客户端不能同时存在两个通道流
     socket.shutdownInput();
 	  bb.write("文件上传完毕");
 	  bb.newLine();
 	  bb.flush();
     b.close();
 	socket.close();
	}
	

}
public class TCPClient {

	public static void main(String[] args) throws UnknownHostException, IOException {
		// TODO Auto-generated method stub
		//1,创建一个TCP客户端,指定目标IP及端口号,已经连上了服务端
      Socket client =new Socket("192.168.1.2",5678);
      //2,从文件中获取输入流
      BufferedReader br =new BufferedReader(new FileReader("test.txt"));
      //3,客户端向服务端的输出流
      BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 
    //4,获取服务端的相应
      BufferedReader bbr =new BufferedReader(new InputStreamReader(client.getInputStream()));     
      String line =null;
      //5,从文件中读取数据,只要读到的不是空,就一直读
      while((line = br.readLine())!=null) {
    	  bw.write(line);
    	  bw.newLine();
    	  bw.flush();
      }
      //关闭Socket的输出流
      client.shutdownOutput();
    System.out.println(bbr.readLine());
       br.close();
      client.close();
	}

案例三:

需求:多个客户端向服务端发送消息,服务端再向客户端响应

步骤:

server

1,建立TCP链接并且绑定端口

ServerSocket server =new ServerSocket(10098);

System.out.println("sever is running");

2,服务端一直监听端口并且创建与客户端的连接

while(true){
Socket socket =server.accept();

System.out.println("a client is connnected")

3,开启一个子线程来处理与客户端的交流(只要客户端代码运行一次,就开启一个客户端(线程))

Handle t =new Handle(socket);

Thread t =new Thread(t);

t.start();

}

4,写线程的具体任务

class Handle implements Runnable{

private Socket socket;

public Handle(Socket socket){

this.socket = socket;

}

public void run(){

//从客户端获取的输入流

InputStream in =socket.getInputStream();

//到客户端的输出流

OutputStream out =socket.getOutputStream();

hander(in,out);

}

}

5,实现hander()方法

public void hander(InputStream in,OutputStream out){

BufferedReader      br =new BufferedReader(new InputStreamReader(in));

BufferedWriter  bw   =new BufferedWriter(new OutputStream(out));

6,服务端先向客户端发送一个消息

bw.write("hello\n");

bw.flush();

7,一直与客户端交流

while(true){

String s =br.readLine();//读取从客户端发来的消息

if(s.equals("888")){

bw.write("888");

bw.flush();

break;

}

bw.write("ok"+s+"\n")

bw.flush();

}

socket.close();

client:

1,创建一个TCP链接并且绑定端口,连上服务器

Socket socket =new Socket("192.168.1.2",10098);

InputStream in =socket.getInputStream();

OutputStream out =socket.getOutputStream();

2,客户端与服务器数据进行交互

hander(in,out);

3,关流

socket.close();

System.out.println("client is disconnected ");

4,重写hander()函数

public  static void hander(InputStream in,OutputStream out){

BufferedReader br =new BufferedReader(new InputStreamReader(in));//从客户端进来的输入流

BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(out));//从客户端出去的流

5,客户端从控制台读入数据

Scanner scanner =new Scanner (System.in);

6,从服务器读取数据

System.out.println("server"+br.readLine());

while(true){

System.out.print("client>>>>>");

String s =scanner.nextLine();

bw.write(s);

bw.newLine();

bw.flush();

String resp =br.readLine();

System.out.println("<<<"+resp);

if(resp.equals("888")){

break;

}

这样就实现了多个客户端与一个服务器进行数据传输

public class TCPServer {
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		//1,建立TCP链接并且绑定端口
		ServerSocket server =new ServerSocket(10088);
		System.out.println("sever is running");
		//2,服务端一直监听端口并且创建与客户端的连接
		while(true) {
			Socket socket =server.accept();
			System.out.println("a clent is connected");
			//3,开启一个子线程来处理与客户端的交流
			Handle t =new Handle(socket);
			Thread t1 =new Thread(t);
			t1.start();
		}
	}
}
class Handle implements  Runnable{
   private Socket socket;
   public Handle(Socket socket) {
	   this.socket = socket;
   }
	@Override
	public void run() {	
		try {
			//从客户端获取的输入流
			InputStream in =socket.getInputStream();
			//到客户端的输出流
			OutputStream out =socket.getOutputStream();
			hander(in,out);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	}
	private void hander(InputStream in, OutputStream out) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader br =new BufferedReader(new InputStreamReader(in));
		BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(out));
		//6,服务端先向客户端发送一个消息
		bw.write("hello\n");
		bw.flush();
		//7,一直与客户端交流
		while(true){
			String s =br.readLine();//读取从客户端发来的消息
			if(s.equals("888")){
			bw.write("888");
			bw.flush();
			break;
			}
			bw.write("ok"+s+"\n");
			bw.flush();
			}
			socket.close();
	}	
}

	public static void main(String[] args) throws UnknownHostException, IOException {
		// TODO Auto-generated method stub
    //1,创建一个TCP链接并且绑定端口,连上服务器
		Socket socket =new Socket("192.168.1.2",10088);
		InputStream in =socket.getInputStream();
		OutputStream out =socket.getOutputStream();
		//2,客户端与服务器数据进行交互
		hander(in,out);
		//3,关流
		socket.close();
		System.out.println("client is disconnected ");
	}
	private static void hander(InputStream in, OutputStream out) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader br =new BufferedReader(new InputStreamReader(in));//从客户端进来的输入流
		BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(out));//从客户端出去的流
	   //5,客户端从控制台读入数据
		Scanner scanner =new Scanner (System.in);
		//6,从服务器读取数据
		System.out.println("server"+br.readLine());
		while(true){
			System.out.print("client>>>>>");
			String s =scanner.nextLine();
			bw.write(s);
			bw.newLine();
			bw.flush();
			String resp =br.readLine();
			System.out.println("<<<"+resp);
			if(resp.equals("888")){
			break;
			}
	}
}

运行结果:

 

 

 

案例四:

需要:实现多客户向服务端传递文件

步骤:

server:

1,建立TCP链接并且绑定端口

ServerSocket server =new ServerSocket(10086);

System.out.println("sever is running");

2,服务端一直监听端口并且创建与客户端的连接

while(true){
Socket socket =server.accept();

System.out.println("a client is connnected")

3,开启一个子线程来处理与客户端的交流(只要客户端代码运行一次,就开启一个客户端(线程))

ReceivedFileTask task =new ReceivedFileTask(socket);

Thread t =new Thread(t);

t.start();

}

4,写线程的具体任务

class ReceivedFileTask implements Runnable{

private Socket socket;

public  ReceivedFileTask(Socket socket){

this.socket = socket;

}

public void run(){

//获取从客户端来的输入流(字节)

BufferedInputStream in = null;

//获取服务端的输出流(向客户端反馈消息) 字符

BufferedWriter out = null;

//获取文件的字节输出流

BufferedOutputStream bos = null;

in = new BufferedInputStream(socket.getInputStream());

out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
 String fileName = FileNameUtil.getName();    //文件名字如果客户端没有上传 服务端自定义 
   bos = new BufferedOutputStream(new FileOutputStream(fileName));

//从服务端的输入流获取数据写入文件中

byte[] buf = new byte[1024];
            int len =0;
            while ((len = in.read(buf)) != -1) {
                bos.write(buf, 0, len);
                bos.flush();
            }

//向服务端反馈

out.write("over");
  out.flush();
    System.out.println("a file has been received.......");

5,关流

socket.close();

if(bos!=null){

bos.close();

}

package part01.网络编程;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

public class TCPClient04 {
	public static void main(String[] args) {
		String ip = "172.16.80.51";
		UpdateFileTask task1 = new UpdateFileTask(ip, "任务1", "周杰伦 - 彩虹.m4a");
		UpdateFileTask task2 = new UpdateFileTask(ip, "任务2", "周杰伦 - 超跑女神.m4a");
		UpdateFileTask task3 = new UpdateFileTask(ip, "任务3", "周杰伦 - 超人不会飞.m4a");
		Thread t1 = new Thread(task1);
		Thread t2 = new Thread(task2);
		Thread t3 = new Thread(task3);
		t1.start();
		t2.start();
		t3.start();
	}
}
class UpdateFileTask implements Runnable {
	private String ip;
	private String taskName;
	private String fileName;
	public UpdateFileTask(String ip, String taskName, String fileName) {
		this.ip = ip;
		this.taskName = taskName;
		this.fileName = fileName;
	}
	@Override
	public void run() {
		System.out.println(taskName + " start......");
		Socket socket = null;
		//获取文件的字节输入流
		BufferedInputStream bis = null;
		//获取客户端向服务端写出数据的输出流
		BufferedOutputStream out = null;
		//获取客户端读取服务端传来的输入流
		BufferedReader in;
		
		try {
			socket = new Socket(ip,10086);
			bis = new BufferedInputStream(new FileInputStream(fileName));
			out = new BufferedOutputStream(socket.getOutputStream());
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			
			byte[] buf = new byte[1024];
			int len = 0;
			while ((len = bis.read(buf)) != -1) {
				out.write(buf, 0, len);
				out.flush();
			}
			
			//获取服务端的响应
			socket.shutdownOutput();
			String resp = in.readLine();
			System.out.println(taskName + resp);
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
}
package part01.网络编程;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

/*
 * 多客户端上传文件 服务端接收
 * */
public class TCPServer04 {
	public static void main(String[] args) throws IOException {
		ServerSocket server = new ServerSocket(10086);
		System.out.println("server running......");
		while (true) {
			Socket socket = server.accept();
			System.out.println("a client connnected......");
			ReceivedFileTask task = new ReceivedFileTask(socket);
			Thread t = new Thread(task);
			t.start();
		}
	}
}
class FileNameUtil {
	private static int number = 1;
	public synchronized static String getName() {
		return "music" + number++ + ".mp3";
	}
}
class ReceivedFileTask implements Runnable {
	private Socket socket;
	
	public ReceivedFileTask(Socket socket) {
		this.socket = socket;
	}

	@Override
	public void run() {
		//获取服务端的输入流(从客户端来的) 字节
		BufferedInputStream in = null;
		//获取服务端的输出流(向客户端反馈消息) 字符
		BufferedWriter out = null;
		//获取文件的字节输出流
		BufferedOutputStream bos = null;
		
		try {
			in = new BufferedInputStream(socket.getInputStream());
			out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
			String fileName = FileNameUtil.getName();	//文件名字如果客户端没有上传 服务端自定义 
			bos = new BufferedOutputStream(new FileOutputStream(fileName));
			
			//从服务端的输入流获取数据写入文件中
			byte[] buf = new byte[1024];
			int len =0;
			while ((len = in.read(buf)) != -1) {
				bos.write(buf, 0, len);
				bos.flush();
			}
			
			//向服务端反馈
			out.write("over");
			out.flush();
			System.out.println("a file has been received.......");
			
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (bos != null) {
				try {
					bos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值