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