网络编程
网络模型
OSI参考模型
TCP/IP参考模型
网络通讯要素
IP地址
端口号
传输协议
1、TCP:
|--特点:面向连接、虚电路连接、有缓冲的传输、全双工通信
|--对象:
|--Socket:用来建立发送 端建立Socket服务的对象,
|--ServerSocket:用来建立接收端建立Socket服务的对象。
因为只有当创建了Socket服务通道时,才能建立端点到端点的连接,进行数据通讯。
|--客户端和服务端建立连接:
|--客户端:
思路:
1、创建TCP的客户端socket服务,使用socket对象完成,建立在创建客户端对象时就明确服务端的端口
Socket s=new Socket("192.168.1.104",10000);
2、如果连接创建成功,因为这传输通道数据(IO)就已经有了,也就是网络IO流已经存在,获取网络IO流对象就可以了,既然是客户端发送数据给服务端,使用输出流。
OutputStream out=s.getOutputStream();
3、通过输出流对象的write方法写入到目的地,目的地就是连接的另一端。
Out.write("TCP哥们我来了".getBytes());
4、关闭资源
S.close();
演示tcp传输。
1,tcp分客户端和服务端。
2,客户端对应的对象是Socket。
服务端对应的对象是ServerSocket。
客户端,
通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机。
因为tcp是面向连接的。所以在建立socket服务时,
就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。
需求:给服务端发送给一个文本数据。
步骤:
1,创建Socket服务。并指定要连接的主机和端口。
import java.io.*;
import java.net.*;
class TcpClient
{
public static void main(String[] args) throws Exception
{
创建客户端的socket服务。指定目的主机和端口
Socket s = new Socket("192.168.1.254",10003);
为了发送数据,应该获取socket流中的输出流。
OutputStream out = s.getOutputStream();
out.write("tcp ge men lai le ".getBytes());
s.close();
}
}
TCP应用遇到的常见问题:
|--IO体系中四个明确中的明确设备中的网络:Socket.getInputStream和Socket.getOutputStream
|--在运行客户端和服务进行交互时,服务端和客户端都再等待,服务端等待的原因是accept方法,客户端等待是因为等待键盘录入,在日常我们最常见的阻塞式方法有read方法和readLine方法,readLine方法比较特殊,只有遇到结束标记换行时,才开始返回,不然它一直读取。
|--客户端录入不了?这就是TCP通讯中最容易产生的问题:等待,因为上面说到的阻塞式方法,因为写入到的数据是写进了缓冲区,并没有到目的地的服务端去,所以不要忘记刷新。
|--服务端读了还是没有数据,readLIne方法有读到,但是没有返回,这是readLine的特点,上面已经说到,只有读到结束标记的时才返回。所以要调用newLine()方法换行才可以。
|--怎么去让服务端知道客户发送数据结束,可是定义标记,比如说over,但是这样的方法是行不通的,当我们要发送的内容当中如果包含了over这样内容,服务端就会在此时中断接收,其实发送端还并没有发送结束,这时我们应该调用shutdownOutput方法即可。
|--改进:使用PrintWriter对象,它对换行操作的时候具备自动刷新功能。
文件上传:
原理:把一个个文件中的内容发送到服务端存储到一个文件中,这就是上传,上传成功后服务端会反馈给客户端:上传成功
客户端思路:
1、读取一个文本文件
2、定义目的是网络,将读取的数据发送到服务端。
实现代码:
Socket s=newSocket("192.168.1.104",10000);
BufferedReaderbuf=new BufferedReader(new FileReader("关联的文件"));
PrintWriterout=new PrintWriter(s.getOutputStream(),true);
Strringline=null;
While((line=bufr.readLine())!=null){
Out.println(line);
}
s.shutdownOutput();//告诉服务端客户端数据发送完毕,其实就是写入了标记。
BufferedReaderbufIn=new BufferedReader(new InputStreamReader(s.getInputStream()));
Stringstr=bufIn.readLine();
Sop(str);
Bufr.close();
S.close();
服务端代码实现:
ServerSocket ss = newServerSocket(10000);
Socket s = ss.accept();
System.out.println(s.getInetAddress().getHostAddress()+".....connected");
BufferedReader bufIn=newBufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter pw = newPrintWriter(new FileWriter("c:\\server.txt"),true);
String line = null;
while((line=bufIn.readLine())!=null){
pw.println(line);
}
PrintWriter out = newPrintWriter(s.getOutputStream(),true);
out.println("上传成功");
pw.close();
s.close();
ss.close();
}
图片上传:
原理:张三首先登陆服务器,李四想要这时候进来的时候不能的,因为服务器所有的代码都再为张三服务,服务器端主要是三样技术:server Socket IO 多线程技术。所以服务端要使用多线程,才能保证多客户端访问。
其中要注意的细节:服务端要不断的接收数据,但是会名字相同的时候会覆盖,所以不能用固定的名称来命名,可以通过定义变量来记录。
服务端实现代码:
class PicThreadimplements Runnable {
private Socket s;
PicThread(Socket s){
this.s = s;
}
public void run() {
String ip =s.getInetAddress().getHostAddress();
try{
int count = 1;
System.out.println(ip+".....connected");
InputStream in = s.getInputStream();
File dir = newFile("c:\\pic");
File file = newFile(dir,ip+".jpg");
while(file.exists()){
file = newFile(dir,ip+"("+(count++)+").jpg");
}
FileOutputStream fos= new FileOutputStream(file);
byte[] buf = newbyte[1024];
int len = 0;
while ((len =in.read(buf)) != -1) {
fos.write(buf,0, len);
}
OutputStream out =s.getOutputStream();
out.write("上传图片成功".getBytes());
fos.close();
s.close();
}catch(IOException e){
e.printStackTrace();
throw newRuntimeException(ip+"... 上传失败");
}
}
}
public classUploadPicServer {
publicstatic void main(String[] args) throws IOException {
ServerSocket ss = newServerSocket(10006);
while(true){
Socket s = ss.accept();
new Thread(newPicThread(s)).start();
}
}
}
客户端实现代码:
stException, IOException {
if(args.length!=1)
thrownew RuntimeException("请选择一个图片文件");
Filefile = new File(args[0]);
if(!file.exists())
thrownew RuntimeException("该文件不存在");
if(!(file.isFile()&& file.getName().endsWith(".jpg")))
thrownew RuntimeException("必须是扩展名为jpg的文件");
if(file.length()>1024*1024*3)
thrownew RuntimeException("疯了吧!");
Sockets = new Socket("192.168.1.100",10006);
FileInputStreamfis = new FileInputStream(file);
OutputStreamout = s.getOutputStream();
byte[]buf = new byte[1024];
intlen = 0;
while((len=fis.read(buf))!=-1){
out.write(buf,0,len);
}
s.shutdownOutput();
InputStreamin = s.getInputStream();
byte[]bufIn = new byte[1024];
intlenIn = in.read(bufIn);
Stringstr = new String(bufIn,0,lenIn);
System.out.println(str);
fis.close();
s.close();
}
浏览器原理:
浏览器是一个客户端,给指定的服务端发送应用层http协议的消息头(是浏览器和服务器之间的规则,其中有
请求行,以及支持的方式,以及客户的信息),
他和服务端之间封装了socket对象。
服务器底层是ServerSocket。
向客户端发送html请求,
两种模式:
1、c/s:client/server
早期开发流行,c++,
特点:客户端和服务端,两端都需要程序员编写,程序员还得安装到用户,
用户用对方开发的客户端,去连接对方开发的服务端,QQ 、360、 酒店管理系统等
弊端:
开发成本偏高,因为既要做客户端也要做服务端。
维护成本高,如果用户要更新,就的拿去安装。
由于网络带宽的提高可以进行网络更新了。
好处:
将部分运算分离到了客户端来完成?
比如说360在本地查杀的时候运行的客户端。不需要去运行服务端。
2、b/s:browser/server
特点:
程序员只需要开发服务端,客户端直接使用系统中已有的软件浏览器即可。
好处:
降低开发和维护成本。客户端什么都不用安装,直接使用系统安装的浏览器即可。
弊端:
所有的运算都在服务端。所以服务器压力相对较大。