网络编程——Java基础

原创 2015年07月09日 02:19:43


一、网络编程概述

网络编程参考模型:OSI模型和TCP/IP模型。

通讯的要素:
IP地址:网络中设备的标识,本地回环地址127.0.0.1,主机名:localhost.
端口号:英语标识进程的逻辑地址,即不同进程的标识,有效端口号为:0~65535,
其中0~1024为系统保留。
传输协议:即通信规则,有UDP、TCP.

代码实例:演示获取主机名,根据主机名获取IP

class IPDemo
{
	public static void main(String [] args)
	{
		InetAddress i = InetAddress.getByName("www.baidu.com");
		System.out.println(i.toString());
		System.out.println("name: "+i.getHostName());
		System.out.println("address: "+i.getHostAddress());
	}
}
UDP:
将数据以及源和目的封装成数据包中,不需要建立连接。
每个数据包大小限制在60k以内。
因为不需要建立连接,是不可靠协议。
无需连接,速度较快
TCP:
建立连接形成数据传输通道。
在连接中进行大数据量传输。
通过三次握手建立连接,可靠协议。
必须要建立连接,效率稍低。
Socket:
为网络服务提供的一种机制。
通信两端都有Socket
网络通信其实就是Socket间通信。
数据在两个Socket之间通过IO传输。
二、使用UDP建立接收和发送端
重点在于掌握UDP的接收端和发送端的建立流程。
定义UDP发送端步骤:
1.建立udpsocket服务。
2.提供数据并将数据封装到数据包中。
3.通过socket服务的发送功能将数据包发送出去。
4.关闭资源。
定义UDP接收端步骤:
定义UDP接收端
1.定义udpsocket服务。通常会监听一个端口,其实就是给这个接收网络
应用程序定义一个数字标识,方便明确哪些数据过来
该应用程序可以处理
2.定义一个数据包,因为要存储接收到的字节数据,因为数据包对象中
3.通过socket服务的receive方法将受到的数据存入已经定义好的数据包中
4.通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台。
5.关闭资源。
代码实例:UDP发送端

import java.net.*;
class UdpSend 
{
	public static void main(String[] args) throws Exception
	{
		//创建udp服务。通过DatagramSocket对象
		DatagramSocket ds=new DatagramSocket();

		//2.确定数据,并封装成数据包。
		byte[] buf="ge men lai le".getBytes();
		DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.0.102"),123);

		//3.通过socket服务将已有的数据包发送出去。通过send方法
		ds.send(dp);

		//4.关闭资源。
		ds.close();

	}
}
代码实例:UDP接收端

class UdpRec
{
	public static void main(String[] args) throws Exception
	{
		//1.创建udp socket。建立端点
		DatagramSocket ds=new DatagramSocket(123);

		while(true)
		{
			//2.定义数据包。用于存储数据。
		byte[] buf=new byte[1024];
		DatagramPacket dp=new DatagramPacket(buf,buf.length);

		//3.通过服务的receive方法将收到的数据存到数据包中
		ds.receive(dp);

		//4.通过数据包的方法获取其中数据
		String ip=dp.getAddress().getHostAddress();

		String data=new String(dp.getData(),0,dp.getLength());

		int port=dp.getPort();

		System.out.println(ip+":::"+data+":::"+port);

		//5.关闭资源
		//ds.close();
		}
		

	}
}
对以上的发送和接收服务端稍加改造,可以实现一个简单的聊天程序
示例代码:

import java.io.*;
import java.net.*;

class  UdpSend2
{
	public static void main(String[] args) throws Exception
	{
		//创建UDP服务对象
		DatagramSocket ds=new DatagramSocket();
		//键盘录入信息
		BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));

		String line=null;
		while((line=bufr.readLine())!=null)
		{
			//结束发送标志
			if("88".equals(line))
				break;
			byte[] buf=line.getBytes();

			//打包
			DatagramPacket dp=
				new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.0.102"),10001);

			ds.send(dp);
		}
		//关闭资源
		ds.close();
	}
}

class UdpRec2
{
	public static void main(String [] args)throws Exception
	{
		//创建接收端对象并监听端口。
		DatagramSocket ds=new DatagramSocket(10001);

		//阻塞
		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+"::"+data);
			
		}
	}
}
三、TCP传输
TCP分为客户端和服务端,客户端对应的对象时Socket,
服务端对应的对象时ServerSocket.
客户端:
在建立Socket对象时就可以去连接指定主机。
因为TCP是面向连接的。所以在建立Socket服务时。
就要有服务端存在。并连接成功。形成通路
在该同道中进行数据传输。
客户端步骤:
1.创建Socket服务。并制定要连接的主机和端口。
2.为了发送数据。应该获取socket流中的输出流。
3.将数据写入到获取的输出流中
4.关闭资源
服务端:
1.建立服务端的socket服务。ServerSocket();
并监听一个端口
2.获取链接过来的客户端对象。
通过ServerSocket的accept方法。这个方法
是阻塞式的。
3.客户端发过来数据。服务端使用对应的客户端对象
并获取到该客户端的读取流。
并打印在控制台。
4.关闭服务端(可选)
客户端示例代码:带反馈信息

class TcpClient
{
	public static void main(String[] args)throws Exception{
		//建立客户端服务,制定主机和端口号
		Socket s = new Socket("192.168.0.102",10001);
		//获取输出流
		OutputStream out = s.getOutputStream();
		//将数据写入到获取的输出流中
		out.write("Tcp Demo".getBytes());
		//获取读取流,用来接收服务端返回信息
		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 TcpServer
{
	public static void main(String[] args)throws Exception{
		//建立服务端,监听端口号。
		ServerSocket ss = new ServerSocket(10001);
		//接收链接过来的客户端对象
		String s = ss.accept();
		//获取一下客户端IP并打印
		String ip = s.getInetAddress().getHostAddress();
		System.out.println(ip+"*****connect");
		//使用对应的客户端获取该客户端的读取流
		InputStream in = s.getInputStream();
		byte[] buf = new byte[1024];
		//读取客户端数据并打印。
		int len = in.read(buf);
		System.out.println(new String(buf,0,len));
		//获得输出流,用来给客户端返回信息
		OutputStream out=s.getOutputStream();
		//将需要反馈的信息写入到输出流
		out.write("Server Accepted Data ok!".getBytes());
		//关闭资源
		s.close();
		//ss.close();

	}
}
示例代码:客户端键盘录入字母发送给服务端,服务端转换成大写,反馈给客户端

package Net;
import java.net.*;
import java.io.*;

//创建客户端,键盘录入信息,传给服务端,并接收服务端反馈的信息
class TransClient {
	public static void main(String[] args)throws Exception{
		//创建客户端服务,指定主机和端口号
		Socket s = new Socket("192.168.0.102",10011);
		//读取键盘录入.源
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
		//关联一个输出流,目的
		PrintWriter out = new PrintWriter(s.getOutputStream(),true);
		//定义一个读取流,接收服务端返回的大写信息
		BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
		
		String line = null;
		while((line = bufr.readLine())!=null)
		{
			//检测到over就结束
			if(line.equals("over"))
				break;
			//将读到的键盘录入信息写入到已经关联的输出流。
			out.println(line);
			//获取服务端返回的信息并打印
			String str = bufIn.readLine();
			System.out.println("server: "+str);
			
		}
		bufr.close();
		s.close();
	}
}
//创建服务端,接收客户端发送过来的信息,进行大写转换后,反馈。
class TransServer{
	public static void main(String[] args)throws Exception{
		//创建服务端,监听端口号
		ServerSocket ss = new ServerSocket(10011);
		//接收并打印客户端IP
		Socket s = ss.accept();
		String ip = s.getInetAddress().getHostAddress();
		System.out.println(ip+"************is connected");
		//获取流中的数据。源
		BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
		//关联输出流,目的
		PrintWriter out = new PrintWriter(s.getOutputStream(),true);
		//进行读取
		String line = null;
		while((line = bufIn.readLine())!=null)
		{
			System.out.println(line);
			//将接收的数据进行大写转换并写到已关联的输出流
			out.println(line.toUpperCase());
		}
		s.close();
	}
}
使用TCP协议,从客户端向服务端传送一个文件。大体思路与上例相似,只不过客户端的源由原来的键盘录入改为
关联一个需要上传的文件,但是注意:传送文件结束标记要用:shutdownOutput();方法。相当于给流一个-1的结束标志;
而服务端的源依然是输入流,目的则改为磁盘,存储客户端传送过来的文件,其实相当于将文件内容复制过来。
具体实现代码如下:

/*
需求:客户端文件内容发送给服务端
	并在服务端保存(相当于copy)
*/

import java.io.*;
import java.net.*;

class  TextClient
{
	public static void main(String[] args) throws Exception
	{
		//创建客户端,指定主机和端口号,关联源和目的。
		Socket s=new Socket("192.168.0.102",10009);
		BufferedReader bufr=
			new BufferedReader(new FileReader("IPDemo.java"));
		PrintWriter out=new PrintWriter(s.getOutputStream(),true);
		//读取关联的文件内容,并写入到已经关联的目的中
		String line=null;
		while((line=bufr.readLine())!=null)
		{
			out.println(line);
		}
		//关闭客户输出流,相当于给流加了一个结束标记-1.
		s.shutdownOutput();
		//创建输入流,接收服务端反馈信息并打印
		BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream()));
		String str=bufIn.readLine();
		System.out.println(str);
		bufr.close();
		s.close();
	}
}
class  TextServer
{
	public static void main(String[] args) throws Exception
	{
		//创建服务端监听端口号获取并打印链接过来的主机IP
		ServerSocket ss=new ServerSocket(10009);
		Socket s=ss.accept();
		String ip=s.getInetAddress().getHostAddress();
		System.out.println(ip+":::connect");
		//创建输入流,关联目的
		BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream()));
		PrintWriter out=new PrintWriter(new FileWriter("Server.txt"),true);
		//读取获取的输入流对象内容并输出到已关联的磁盘文件中
		String line=null;
		while((line=bufIn.readLine())!=null)
		{
			out.println(line);
		}
		//反馈信息
		PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
		pw.println("上传成功");		
		out.close();
		s.close();
		ss.close();
	}
}
并发访问服务端实例:客户端在控制台指定一个规定格式的文件上传到服务端,
且可以实现多个客户端同时上传。这就用到了多线程,将每个连接过来的客户端都封装成一个
对象,用该对象创建一个线程,而每个线程要执行的代码是相同的,可以将该代码写在run方法
中,
代码实例:

/*
需求:上传图片。
在控制台指定需要上传的文件。

*/

/*
客户端:
1.服务端点
2.读取客户端已有的图片数据
3.通过socket输出流将数据发给服务端。
4.读取服务端反馈信息。
5.关闭
*/
import java.net.*;
import java.io.*;
class  PicClient
{
	public static void main(String[] args) throws Exception
	{
		//客户端读取已有图片(待定文件)源
		FileInputStream fis=new FileInputStream(file);
		//在客户端指定要选择的文件的格式要求。
		if(args.length!=1)
		{
			System.out.println("请选择jpg格式图片");
			return;
		}
		File file=new File(args[0]);
		if(!(file.exists())&& file.isFile())
		{
			System.out.println("文件不存在或者不是文件");
			return;
		}
		if(!file.getName().endsWith(".jpg"))
		{
			System.out.println("图片格式错误");
			return;
		}
		if(file.length()>1024*1024*5)
		{
			System.out.println("文件过大!");
			return;
		}
		//如果指定文件满足格式要求,创建服务端点 IP Port
		Socket s=new Socket("192.168.0.102",10010);		
		//创建输出字节流。目的
		OutputStream out=s.getOutputStream();
		//创建缓冲区
		byte[] buf=new byte[1024];
		int len=0;
		while((len=fis.read(buf))!=-1)
		{
			//将指定的文件写入到输出流中
			out.write(buf,0,len);
		}
		//告诉服务端写完,让服务端结束读循环
		s.shutdownOutput();
		//创建输入字节流,用以获取反馈信息
		InputStream in=s.getInputStream();
		//缓冲区接收服务端反馈信息并打印
		byte[] bufIn=new byte[1024];
		int num=in.read(bufIn);
		System.out.println(new String(bufIn,0,num));
		fis.close();
		s.close();
	}
}
/*
定义每个线程共同执行的代码
*/
class PicThread implements Runnable
{
	//需要传入一个对象
	private Socket s;
	PicThread(Socket s)
	{
		this.s=s;
	}	
	public void run()
	{
		//获取该对象的主机名
		String ip=s.getInetAddress().getHostAddress();
		try
		{
			int count=0;
			System.out.println(ip+"****connect");
			//数据输入读取流
			InputStream in=s.getInputStream();	
			//多次上传命名
			File file=new File(ip+"("+(count)+")"+".jpg");
			while(file.exists())//如果已经存在就让count加1再存储。
				file=new File(ip+"("+(count++)+")"+".jpg");
			//保存数据
			FileOutputStream fos=new FileOutputStream(file);
			byte[] buf=new byte[1024];
			int len=0;
			while((len=in.read(buf))!=-1)
			{
				//写入数据到ser.bmp
				fos.write(buf,0,len);
			}
			//给客户端反馈信息
			OutputStream out=s.getOutputStream();	
			out.write("上传成功".getBytes());
			fos.close();
			s.close();
		}
		catch (Exception e)
		{
			throw new RuntimeException(ip+"获取失败");
		}
	}
}
/*服务端:
为了同时处理多个客户端的请求。将每个客户端封装到一个单独的
	线程中,这样就可以同时处理多个客户请求
如何定义线程呢?
只要明确了每一个客户端要在服务端执行的代码即可,将该代码
	存入run方法中。*/
class PicServer 
{
	public static void main(String[] args) throws Exception
	{
		//建立服务 监控端口号
		ServerSocket ss=new ServerSocket(10010);
		while(true)
		{
			//等待获取客户端,将接收到的客户端封装成对象,
			Socket s=ss.accept();
			//将接收到的客户端对象创建线程,(每接收一个对象就创建一个线程,实现并发访问)
			new Thread(new PicThread(s)).start();
		}
		//ss.close();
	}
}
四、浏览器作为客户端,服务端:自定义和Tomcat服务器
示例代码:

import java.net.*;
import java.io.*;

class ServerDemo 
{
	public static void main(String[] args) throws Exception
	{
		ServerSocket ss=new ServerSocket(10001);

		//获取客户端数据
		Socket s=ss.accept();
		//获取客户端地址
		System.out.println(s.getInetAddress().getHostAddress());
		//获取客户端请求信息
		InputStream in=s.getInputStream();

		byte[] buf=new byte[1024];

		int len=in.read(buf);

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

		//给客户端发送反馈信息
		PrintWriter out=new PrintWriter(s.getOutputStream(),true);

		out.println("<font color='red' size='7'>客户端你好</font>");

		s.close();
		ss.close();
	}
}
五、小知识
关于InetAddress和InetSocketAddress的区别:
InetAddress代表IP地址,InetSocketAddress代表的IP+port。
域名解析:
想要将主机名翻译成ip地址,就需要域名解析,DNS.
域名和ip的映射关系存放在本机的C:\Windows\System32\drivers\etc\host文件中,
我们可以更改恶意网站域名对应的IP来达到避免被恶意网站感染。
URL地址解析:
String getFile() 
          获取此 URL 的文件名。 
String getHost() 
          获取此 URL 的主机名(如果适用)。 
String getPath() 
          获取此 URL 的路径部分。 
int getPort() 
          获取此 URL 的端口号。 
String getProtocol() 
          获取此 URL 的协议名称。 
String getQuery() 
          获取此 URL 的查询部分。 
示例代码:

import java.net.*;
class  URLDemo
{
	public static void main(String[] args) throws MalformedURLException

	{
		//定义一个URL地址
		URL url=new URL("http://192.168.0.102:8080/myweb/demo.html?haha&hello=90");
		//解析
		System.out.println("getProtocol() :"+url.getProtocol());
		System.out.println("getHost() :"+url.getHost());
		System.out.println("getPort() :"+url.getPort());
		System.out.println("getPath() :"+url.getPath());
		System.out.println("getFile() :"+url.getFile());
		System.out.println("getQuery() :"+url.getQuery());

//		int port=url.getPort();
//		返回-1则指定默认端口
//		if(port==-1)
//			port=80;
	}
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

java网络编程基础知识

java网络编程基础知识 一、网络基本概念 1、计算机网络,就是把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息,...
  • wfgeqgeq
  • wfgeqgeq
  • 2011年09月19日 19:24
  • 3382

Java基础之网络编程知识点总结

网络编程----Java语言涵盖的领域很广,对于网络方面,java也是相当棒的,java也是可以完成网络通讯的功能的...
  • u011460827
  • u011460827
  • 2014年12月01日 22:00
  • 1751

java 之 API-网络编程

网络编程概述计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机...
  • LiuMiao1128
  • LiuMiao1128
  • 2016年11月19日 15:15
  • 278

网络编程基础概述

网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习。 在 学...
  • w627782664
  • w627782664
  • 2011年12月27日 19:59
  • 6526

网络编程2--毕向东java基础教程视频学习笔记

转载地址:http://www.cnblogs.com/wsw-tcsygrwfqd/p/5131781.html Day 23 08 Udp接收端 09 Udp键盘录入...
  • l_215851356
  • l_215851356
  • 2017年03月12日 16:48
  • 227

全栈必备 网络编程基础

或许,老码农说的都是错的,了解了所谓的网络基础,也不一定写出漂亮的代码,不了解所谓的网络基础,也不一定写不出漂亮的代码,全当他自言自语吧。...
  • wireless_com
  • wireless_com
  • 2017年01月30日 00:00
  • 3922

JavaScript---网络编程(1)-介绍、变量、运算符与语句

JavaScript也是一种编程语言。并不是Java的分支哦。 可以直接在浏览器中运行的编程语言。JavaScript 的历史故事: 1、JavaScript语言与名称的由来(Netscape,S...
  • qq_26525215
  • qq_26525215
  • 2016年05月29日 18:39
  • 6092

java并发编程——一并发基础

为什么使用多线程 多任务的处理,提高处理速度,减少相应时间,更好的体验 随着cpu的核心数量越来越多,提供了充足的硬件基础,使用多线程重复发挥机器的计算能力,合理利用资源 上下文切换cpu通过给每个线...
  • lemon89
  • lemon89
  • 2016年06月29日 09:51
  • 568

Android网络编程基础(一) - 基础知识

内容介绍:Android网络编程基础 博客地址:http://blog.csdn.net/kevindgk 版权声明:本文为原创文章,未经允许不得转载 联系方式:815852777...
  • KevinDGK
  • KevinDGK
  • 2016年08月16日 17:45
  • 2310

socket网络编程的一些基础知识

目录: 1) 什么是套接字? 2) Internet 套接字的两种类型 3) 网络理论 4) 结构体 5) 本机转换 6) IP 地址和如何处理它们 7) socket()函数 8) bind()函数...
  • roger_77
  • roger_77
  • 2006年12月22日 11:17
  • 6784
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:网络编程——Java基础
举报原因:
原因补充:

(最多只允许输入30个字)