您的位置:首页 > 理论基础 > 计算机网络

黑马程序员-----网络编程(2)

2015-08-24 18:03 651 查看
——- android培训java培训、期待与您交流! ———-

一、基于TCP协议的网络编程——-客户端和服务端

1、TCP传输的思路:(步骤)

1)用Socket和serverSocket来建立客户端和服务器端
2)建立连接后,通过Socket中的IO流进行数据的传输
3)关闭Socket
注:客户端和服务器端是两个独立的应用程序。


2、客户端

1)通过查阅Socket对象,发现在该对象建立时,就可以去连接指定主机,因为TCP是面向连接的,所以在建立Socket服务时,就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。

2)建立客户端的思路

1、创建Socket服务,并指定要连接的主机和端口
2、为了发送数据,应该获取Socket流中的输出流


3)示例演示:给服务端发送一个文本数据(客户端的例子)

package com.tcpudplianxi;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

/**需求:给服务端发送一个文本数据(客户端的例子)
* @param args
*/
public class MyClient {

public static void main(String[] args) throws UnknownHostException, IOException {
//创建客户端的Socket服务
Socket s=new Socket("127.0.0.1",10008);
//为了发送数据,获取Socket流中的输出流
OutputStream out=s.getOutputStream();
out.write("服务器,你好 ".getBytes());
s.close();
}

}


3、服务器端

建立服务端的思路:

1)  建立服务端的Socket服务,serverSocket(),并监听一个端口。
2)  获取连接过来的客户端的对象,通过serverSocket的accept方法。没有连接就会等,所以这个方法时阻塞式的。
3)  客户端如果发过来数据,那么服务端就会使用对应的客户端对象,并获取到客户端对象的读取流来读取发过来的数据,并打印在控制台。
4)  关闭服务器(可选)


5) 示例演示:定义端点接收数据并打印在控制台上(服务器端的例子)

package com.tcpudplianxi;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**需求:定义端点接收数据并打印在控制台上(服务器端的例子)
* @param args
*/
public class MyServr {

public static void main(String[] args) throws IOException {
//建立服务端的Socket服务,并监听一个端口
ServerSocket ss=new ServerSocket(10008);
//通过accept方法获取连接过来的客户端对象
Socket s=ss.accept();
String ip=s.getInetAddress().getHostAddress();
System.out.println(ip+"....is connected");
//获取客户端发送过来的数据,那么要使用客户端对象读取流来读取数据
InputStream in=s.getInputStream();
byte[] buf=new byte[1024];
int len=in.read();
System.out.println(new String(buf,0,len));
s.close();
ss.close();//服务器通常情况下是不关闭的,这是只连接一次服务器情况。

}

}


二、TCP的传输的客户端和服务器的互访

总结:

**对于网络编程而言,重要的是理解其步骤,按照步骤一步步进行搭建!

客户端和服务端需要交互,那么就要构建相对应的流,供其输入和输出!

对于阻塞式方法,一定要提供停止标签,告诉服务器已写完数据

对于PrintWriter ,记得用println而不是write;不要忘了加上true,自动刷新!**

练习一:客户端给服务器发送数据,服务端接收后,给客户端发反馈信息

代码演示:

package com.tcpudplianxi;

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

/**
* 需求:客户端给服务器发送数据,服务端接收后,给客户端发反馈信息
* @author ling
*
*/
public class TcpClient {

public static void main(String[] args) throws Exception {
//建立服务,连接主机和端口
Socket s=new Socket("172.18.254.7",10009);
//获取Socket流中的输出流,将数据写到该流中
OutputStream out=s.getOutputStream();
out.write("服务器,你好".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();
}

}

package com.tcpudplianxi;

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

public class TcpServer {

public static void main(String[] args) throws Exception {
ServerSocket ss=new ServerSocket(10009);
Socket s=ss.accept();
String ip=s.getInetAddress().getHostAddress();
System.out.println(ip+"...connected");
//服务器收到的数据要先读出来
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("我收到回复了,你也好!".getBytes());
s.close();
ss.close();

}

}


练习二: 建立一个文本转换服务器。客户端给服务端发送文本,服务端会将文本转成大写再返回给客户端。而且客户端可以不断的进行文本转换,当客户端输入over时,转换结束。

客户端代码:

package com.tcpudplianxi;
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;

/**需求:建立一个文本转换服务器。客户端给服务端发送文本,服务端会将文本转成大写再返回给客户端。
* 而且客户端可以不断的进行文本转换,当客户端输入over时,转换结束。
*
* 分析:既然是操作设备上的数据,那么就可以使用io技术,并按照io的操作规律来思考。
*     源:键盘录入
*     目的:网络设备,网络输出流(因为是操作的文本数据,所以是字符流)
* @param args
*/
public class TransClient {
public static void main(String[] args) throws UnknownHostException, IOException {
//建立Socket服务
Socket s=new Socket("172.18.254.7",10006);
//获取键盘输入的流对象
BufferedReader  bufr=new BufferedReader(new InputStreamReader(System.in));
//定义目的,将数据写入Socket输出流,发给服务端
BufferedWriter  bufout=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//定义一个Socket读取流,读取服务端返回的大写信息
BufferedReader  bufin=new BufferedReader(new InputStreamReader(s.getInputStream()));
String line=null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
bufout.write(line);
bufout.newLine();
bufout.flush();
String str=bufin.readLine();
System.out.println("server:"+str);

}
bufr.close();
s.close();
}
}


服务端代码:

package com.tcpudplianxi;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class TransServer {

public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(10006);
Socket s=ss.accept();
String ip=s.getInetAddress().getHostAddress();
System.out.println(ip+"....connected");
//读取Socket,读取流中的数据
BufferedReader  bufin=new  BufferedReader(new InputStreamReader(s.getInputStream()));
//目的Socket输出流,将大写数据写入到Socket输出流,并发给客户端
BufferedWriter  bufout=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line=null;
while((line=bufin.readLine())!=null)
{
System.out.println(line);
bufout.write(line.toUpperCase());
bufout.newLine();
bufout.flush();

}
s.close();
ss.close();

}

}


练习三:上传文件(复制文件)。通过客户端上传一个文件给服务器,服务器再把它保存赋值起来。

客户端代码:

package com.tcpudplianxi;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

/**需求:上传文件
* @param args
*/
public class TextClient {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket s=new Socket("172.18.254.7",10003);
BufferedReader bufr=new BufferedReader(new FileReader("lianxi01.java"));
PrintWriter out=new PrintWriter(s.getOutputStream(),true);
String line=null;
while((line=bufr.readLine())!=null)
{
out.println(line);
}
s.shutdownOutput();//关闭客户端的输出流,相当于给流中加入一个结束标记-1
BufferedReader  bufin=new BufferedReader(new InputStreamReader(s.getInputStream()));
String str=bufin.readLine();
System.out.println(str);
bufr.close();
s.close();

}

}


服务端的代码:

package com.tcpudplianxi;

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

public class TextServer {

public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(10003);
Socket s=ss.accept();
BufferedReader bufin=new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter pw=new PrintWriter(new FileWriter("server.txt"),true);
String line=null;
while((line=bufin.readLine())!=null)
{
pw.println(line);
}
PrintWriter out=new PrintWriter(s.getOutputStream(),true);
out.println("上传成功!");
pw.close();
ss.close();
s.close();

}

}


练习四:上传图片(单人上传)

客户端代码:

package com.tcpudplianxi;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

/**需求:上传一个图片(单人上传)
* 分析:因为图片是二进制文件,所以是字节流
* @param args
*/
public class PicClient {

public static void main(String[] args) throws UnknownHostException, IOException {
Socket s=new Socket("172.18,254,7",10002);
FileInputStream fis = new FileInputStream("赞.jpg");
OutputStream out=s.getOutputStream();
byte[] buf=new byte[1024];
int len=0;
while((len=fis.read())!=-1)
{
out.write(buf,0,len);
}
s.shutdownOutput();//告诉服务器数据已写完

InputStream in=s.getInputStream();
byte[] bufin=new byte[1024];
int num=0;
System.out.println(new String(bufin,0,num));
fis.close();
s.close();

}

}


服务器端代码:

package com.tcpudplianxi;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class PicServer {

public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(10002);
Socket s=ss.accept();
InputStream in=s.getInputStream();
FileOutputStream  fos=new FileOutputStream("server.jpg");
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();
ss.close();

}

}


练习五:客户端并发登录。客户端通过键盘录入用户名,服务器对这个用户名进行校验:

1) 如果该用户存在,在服务端显示“xxx,已登录”,并在客户端显示:“xxx,欢迎光临”

2) 如果该用户不存在,在服务端显示“xxx,尝试登录”,并在客户端显示:“xxx,该用户不存在”

3) 最多登录三次。

代码演示:

package com.tcpudplianxi;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

/**需求:客户端通过键盘录入用户名,服务器对这个用户名进行校验:
1)  如果该用户存在,在服务端显示“xxx,已登录”,并在客户端显示:“xxx,欢迎光临”
2)  如果该用户不存在,在服务端显示“xxx,尝试登录”,并在客户端显示:“xxx,该用户不存在”
3)  最多登录三次。
*/
public class LoginClient {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket s=new Socket("172.18,254,7",10001);
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
BufferedReader  bufin=new BufferedReader(new InputStreamReader(s.getInputStream()));
for(int x=0;x<3;x++)
{
String line=bufr.readLine();
if(line==null)
break;
pw.println(line); //获取键盘录入的信息,并发布出去String
String info=bufin.readLine();//读取服务器的反馈信息
System.out.println("info:"+info);
if(info.contains("欢迎"))
break;

}
bufr.close();
s.close();

}
}

class LoginServer
{
public static void main(String[] args) throws IOException
{
ServerSocket ss=new ServerSocket(10001);
while(true)
{
Socket s=ss.accept();
new Thread(new UserThead(s)).start();

}
}
}

class UserThead implements Runnable
{
private Socket s;
UserThead(Socket s)
{this.s=s;}
public void run()
{
String ip=s.getInetAddress().getHostAddress();
System.out.println(ip+"....connected");
try
{
for(int x=0;x<3;x++)
{
//读取Socket,读取流中的数据
BufferedReader  bufin=new  BufferedReader(new InputStreamReader(s.getInputStream()));
String name=bufin.readLine();
if(name==null)
break;
BufferedReader bufr=new BufferedReader(new FileReader("user.txt"));
PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
String line=null;
boolean flag=false;
while((line=bufr.readLine())!=null)
{
if(line.equals(name))
{
flag=true;
break;
}

}
if(flag)
{
System.out.println(name+",已登录");
pw.println(name+",欢迎光临");
break;
}
else
{
System.out.println(name+",尝试登陆");
pw.println(name+",用户名不存在");
}
}

s.close();
}
catch(Exception e )
{
throw new RuntimeException(ip+"校验失败");

}
}
}


总结:

1、  为了可以让多个客户端同时并发访问服务器,那么服务器端最好将每个客户端封装到一个单独的线程中,这样就可以同时处理多个客户端请求、
2、  如何定义多线程呢?
只要明确每一个客户端要在服务器执行的代码即可,将该代码存入run方法中。


三、URL和URLConnection类

1、URL:统一资源管理器

2、常用的方法:

1)String  getFile():获取此URL的文件名
2)String  getHost():获取此URL的主机名
3) String  getPath():获取此URL的路径部分
4)int  getPort():获取此URL的端口号
5)String  getProtocol():获取此URL的协议名称
6)String  getQuery():获取此URL的查询部


3、示例演示:

package com.tcpudplianxi;
import java.net.MalformedURLException;
import java.net.URL;

public class UrlDemo {

public static void main(String[] args) throws MalformedURLException {
URL url=new URL("Http://172.18.254.7:8080//myweb/demo.html?name=haha&age=30");
System.out.println("协议名称:"+url.getProtocol()); //返回http
System.out.println("主机名:"+url.getHost()); //返回172.18.254.7
System.out.println("端口号:"+url.getPort());//返回8080
System.out.println("路径:"+url.getPath());//返回/myweb/demo.html
System.out.println("文件名:"+url.getFile());//返回/myweb/demo.html?name=haha&age=30
System.out.println("查询部:"+url.getQuery());  //返回name=haha&age=30

}

}


**注意:如果URL中没有指定端口时,系统会返回Port为-1,即默认端口为80**


4、URLConnection类:抽象类,代表应用程序和URL之间的通信连接

常用的方法:

1) openConnection():返回一个URLConnection对象,它表示到URL所引用的远程对象的连接。

2) openStream():打开到此URL的连接并返回一个用于从该连接读入的InputStream

此方法是下面方法的缩写:openConnection().getInputStream

3) getContent():获取此URL的内容。

此方法是下面方法的缩写:openConnection().getContent();

——- android培训java培训、期待与您交流! ———-
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: