黑马程序员-网络编程之TCP传输小总结

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------


TCP传输:

Socket和ServerSocket分别表示TCP传输的两个端点,客户端和服务端,不同于UDP的DatagramSocket类既可以表示接收端也可以表示发送端。
客户端:
//创建客户端的Socket服务,指定目的主机和端口
//这一步一旦建立成功,就客户端和服务端之间就形成了字节流
Socket s=new Socket("127.0.0.1",10004);

//为了发送数据,应该获取Socket中的输出流。这个输出流是将字节写入此客户端Socket。一旦写入,就发送给服务器端。
//s.getOutputStream()对象的目的是服务器端中此Socket对象A对应的一个Socket对象A‘。服务器端将A'实例化后
//就通过A'的getInputStream()流的read来获取A的getOutputStream()流write出的数据。
OutputStream out=s.getOutputStream();

out.write("tcp ge men lai le".getBytes());

s.close();
服务器端:
//监理服务端socket服务,并监听一个端口。
ServerSocket ss=new ServerSocket(10004);

//通过accept方法获取链接过来的客户端Socket对象。
//accept方法是一个阻塞式方法,启动后会一直监听等着一个Socket来链接
Socket s=ss.accept();

//得到客户端对象的ip地址
String ip=s.getInetAddress().getHostAddress();
System.out.println(ip+"..connected");

//获取客户端发送过来的数据,那么先在服务器端实例化一个客户端对应的Socket对象,然后通过这 //个对象的getInputStream()
//流来获取客户端write出的数据
//s.getInputStream()流对象的源是客户端此Socket
InputStream in=s.getInputStream();

byte[]buf=new byte[1024];
int len=in.read(buf);
System.out.println(new String(buf,0,len));

s.close();//关闭客户端。服务端一般情况下可以关闭客户端,但是不关闭服务端自己
ss.close();//关闭服务端,可选操作

注意,说白了,其实就是客户端和服务端都有一个Socket对象,这两个对象都有自己的读写流,我写你读,我读你写。

/*演示Tcp传输
 * 1 Tcp分客户端和服务端。
 * 2 客户端对应的对象是Socket,服务端对应的对象是ServerSocket
 * 
 * 
 * */

/*
 * 需求:给服务端发送一个文本数据。
 * 客户端:通过查阅socket对象,发现在该对象建立时,就可以连接指定主机。
 * 因为tcp是面向连接的,所以在建立socket服务时就要有服务端存在并连接成功。形成通路后,在该通道形成数据的传输
 * 步奏:
 * 1,创建Socket服务,并指定要连接的主机和端口。
 * 2,
 * */
class TCPClient{
	public static void main(String []args) throws Exception{
		//创建客户端的Socket服务,指定目的主机和端口
		//这一步一旦建立成功,就客户端和服务端之间就形成了字节流
		Socket s=new Socket("127.0.0.1",10004);
		
		//为了发送数据,应该获取Socket中的输出流。这个输出流是将字节写入此客户端Socket。一旦写入,就发送给服务器端。
		//s.getOutputStream()对象的目的是服务器端中此Socket对象A对应的一个Socket对象A‘。服务器端将A'实例化后
		//就通过A'的getInputStream()流的read来获取A的getOutputStream()流write出的数据。
		OutputStream out=s.getOutputStream();
		
		
		out.write("tcp ge men lai le".getBytes());
		
		s.close();
	}
}


/*
 * 需求:定义端点接收数据并打印在控制台上。
 * 
 * 服务端:
 * 1,建立服务端的Socket服务,通过ServerSocket()建立,并监听一个端口
 * 2,获取链接过来的客户端对象。通过ServerSocket的accept方法。所以这个方是阻塞式的
 * 3,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据并打印
 *    在控制台。
 * 4,关闭服务端。(可选)
 * */

class TCPServer{
	public static void main(String[]args) throws Exception{
		//监理服务端socket服务,并监听一个端口。
		ServerSocket ss=new ServerSocket(10004);
		
		//通过accept方法获取链接过来的客户端Socket对象。
		//accept方法是一个阻塞式方法,启动后会一直监听等着一个Socket来链接
		Socket s=ss.accept();
		
		//得到客户端对象的ip地址
		String ip=s.getInetAddress().getHostAddress();
		System.out.println(ip+"..connected");
		
		//获取客户端发送过来的数据,那么先在服务器端实例化一个客户端对应的Socket对象,然后通过这个对象的getInputStream()
		//流来获取客户端write出的数据
		//s.getInputStream()流对象的源是客户端此Socket
		InputStream in=s.getInputStream();
		
		byte[]buf=new byte[1024];
		int len=in.read(buf);
		System.out.println(new String(buf,0,len));
			
		s.close();//关闭客户端。服务端一般情况下可以关闭客户端,但是不关闭服务端自己
		ss.close();//关闭服务端,可选操作
	}
}

/*演示tcp传输的客户端和服务端的互访。
 * 需求:客户端给服务端发送数据,服务端收到后,给客户端反馈信息。
 * */

/*
 * 客户端:
 * 1,建立socket服务。指定要连接的主机和端口
 * 2,获取socket流中的输出流,将数据写到该流中,通过网络发送到服务端
 * 3,获取socket流中的输入流,将服务端反馈的数据获取到,并打印
 * 4,关闭客户端资源
 * */
class TcpClient2{
	public static void main(String[]args) throws Exception{
		Socket s=new Socket("127.0.0.1",10004);
		OutputStream out=s.getOutputStream();
		out.write("服务端你好!".getBytes());
		
		//同样道理,客户端的Socket对象的getInputStream流的源是服务端的相应Socket对象,它write后我read
		InputStream in=s.getInputStream();
		
		byte[] buf=new byte[1024];
		int len=in.read(buf);
		
		System.out.println(new String(buf,0,len));
		s.close();
	}
}

class TcpServer2{
	public static void main(String[]args) throws Exception{
		ServerSocket ss=new ServerSocket(10004);
		
		Socket s=ss.accept();
		
		String ip=s.getLocalAddress().getHostAddress();
		
		System.out.println(ip+" ..connected");
		
		InputStream in=s.getInputStream();
		
		byte[] buf=new byte[1024];
		
		int len=in.read(buf);//read方法也是阻塞式的,客户端不来数据我就在这里等数据
		
		System.out.println(ip+"::"+new String(buf,0,len));
		
		OutputStream out=s.getOutputStream();
		
		out.write("哥们收到!你也好!".getBytes() );
		
		ss.close();
	}
}


通过服务器端实现对输入字符串大小写互换功能。

/*
 * 需求:建立一个文本转换器。
 * 客户端给服务端发送文本,服务端会将文本转成大写返回给客户端。
 * 而且客户端可以不断的进行文本转换,当客户端输入over时,转换结束。
 * */
class TcpClient3{
	
	static BufferedReader br;
	static BufferedWriter bf;
	static BufferedReader br1;
	
	public static void main(String[]args) throws Exception{
		Socket s=new Socket("127.0.0.1",10005);
		OutputStream out=s.getOutputStream();
		
		
		br=new BufferedReader(new InputStreamReader(System.in));//读取键盘输入
		bf=new BufferedWriter(new OutputStreamWriter(out));//发送到服务端
		br1=new BufferedReader(new InputStreamReader(s.getInputStream()));//读取服务端发来的数据
		
		System.out.println("请输入:");
		
		String line=null;
		while((line=br.readLine())!=null ){//键盘输入若干字符和一个回车表示一行,readLine()读取了字符舍弃回车符。也就是说line中不包含回车符
			if(line.equals("over")) break;
			bf.write(line);
			bf.newLine();//再写入一个回车符
			bf.flush();
			System.out.println("服务器说:"+br1.readLine());
			}
		
		s.close();
		bf.close();
		br.close();
		br1.close();
	}
}

class TcpServer3{
	public static void main(String[]args) throws Exception{
		ServerSocket ss=new ServerSocket(10005);
		Socket s=ss.accept();
		String ip=s.getInetAddress().getHostAddress();
		System.out.println("ip:"+ip+"...connected");
		
		BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
		BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

		String line=null;
		while((line=br.readLine())!=null){
		
			System.out.println(line);
			
			char b[]=line.toCharArray();
			
			for(int i=0;i<b.length;i++){
				if(b[i]<='z' && b[i]>='a')b[i]-=32;
				else if(b[i]<='Z' && b[i]>='A')b[i]+=32;
			}
			
			bw.write(new String(b));
			bw.newLine();
			bw.flush();
	
		}
	}
}

向服务器上传文本文件。

class TextClient{
	public static void main(String[]args) throws Exception{
		Socket s=new Socket("127.0.0.1",10006);
		
		BufferedReader br=new BufferedReader(new FileReader("D:\\workspace\\exam\\src\\com\\itheima\\Test9.java"));
		
		PrintWriter out=new PrintWriter(s.getOutputStream(),true);
		
		String line=null;
		
		while((line=br.readLine())!=null){
			out.println(line);
		}
		
		s.shutdownOutput();//关闭客户端的输出流。相当于给流中加入一个结束标记-1.
		
		BufferedReader bufin=new BufferedReader(new InputStreamReader(s.getInputStream()));
		
		String line1=bufin.readLine();
		
		System.out.println(line1);
		
	br.close();
		
		s.close();
		
		bufin.close();
	}
}

class TextServer{
	public static void main(String []args) throws Exception{
		ServerSocket ss=new ServerSocket(10006);
		Socket s=ss.accept();
		String ip=s.getInetAddress().getHostAddress();
		System.out.println(ip+" connnected");
		BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
		PrintWriter out=new PrintWriter(new FileWriter("Server.txt"));
		String line=null;
		while((line=br.readLine())!=null){
			out.println(line);
		}
		PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
		pw.println("恭喜你,上传成功!");
		out.close();
		s.close();
		ss.close();
	}
}

并行向服务器上传图片。思想是服务端做成多线程。

/*向服务器上传图片*/

/*
 * 客户端:
 * 1,服务端点
 * 2,读取客户端已有的图片数据
 * 3,通过socket输出流发送给服务端
 * 4,读取服务端反馈信息
 * 5,关闭
 * */
class UpClient{
	public static void main(String[]args) throws Exception{
		if(args.length!=1){
			System.out.println("请选择一个图片文件");
			return;
		}
		File file=new File(args[0]);
		if(!(file.exists() && file.isFile())){
			System.out.println("文件不存在或不是文件");
			return;
		}
		
		if(!args[0].endsWith(".jpg")){
			System.out.println("请选择jpg文件");
			return;
		}
		
		if(file.length()>1024*1025*5){
			System.out.println("请选择小于5m的图片");
			return;
		}
		
		Socket s=new Socket("127.0.0.1",10007);
		BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));
		BufferedOutputStream bos=new BufferedOutputStream(s.getOutputStream());
		BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
		
		byte[] b=new byte[1024];
		int len;
		while((len=bis.read(b))!=-1){
			bos.write(b, 0, len);
			bos.flush();
		}
		s.shutdownOutput();
		
		System.out.println(br.readLine());
		
		s.close();
		bis.close();
		bos.close();
		br.close();
	}
}

/*
 * 服务端的服务代码都写在线程类中,以实现并发。
 * */
class PicThread implements Runnable{
	private Socket s;
	PicThread(Socket s){
		this.s=s;
	}
	public void run(){
		String ip=s.getInetAddress().getHostAddress();
		int count=1;
		try {
			System.out.println(ip+"...connected");
			BufferedInputStream bis;
			
			bis = new BufferedInputStream(s.getInputStream());
			
			File file=new File("D:\\"+ip+"("+count+").jpg");//同一客户端发过来的图片名称都定义为它的ip号,以区别其他客户端
			while(file.exists()){//如果此名称已存在,即已有这个客户端发来图片,那么新传来的图片尾号自动加1,防止同名覆盖
				file=new File("D:\\"+ip+"("+(++count)+").jpg");	
			}
			
			BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(file));
			PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
			
			int len;
			byte[] b=new byte[1024];
			while((len=bis.read(b))!=-1){
				bos.write(b, 0, len);
			}
			pw.println("上传完毕");
			
			s.close();
			bis.close();
			bos.close();
			pw.close();
		} catch (Exception e) {
			throw new RuntimeException(ip+"...上传失败");
		}
		
	}
}

/*
 * 服务器原理:
 * 将服务代码写入线程run方法,这样每次接收到一个新的请求时就开启一个线程。
 * 之后主线程再次accept阻塞等待,再来新请求再次开启一个新线程。
 * */
class UpServer{
	public static void main(String[]args) throws Exception{
		ServerSocket ss=new ServerSocket(10007);
		while(true){
			Socket s=ss.accept();
			new Thread(new PicThread(s)).start();
		}
	}
}



---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值