网络编程

来源:互联网 发布:付费网络推广方式 编辑:程序博客网 时间:2024/05/20 15:57

网络模型:

OSI

TCP\IP

IP地址:网络设备中的标识

端口:用于标识进程的逻辑地址,不同进程的标识。有效端口:0~65535,其中0~1024为系统使用或保留窗口。

传输协议

UDP

将数据及源和目的封装成数据包中,不需要建立连接

每个数据包的大小限制在64k内

因无连接,是不可靠协议

不需要建立连接,速度快

TCP

建立连接,形成传输数据的通道。

在连接中进行大数据量传输

通过三次握手完成连接,是可靠协议

必须建立连接,效率会稍低

关于IP、InetAddress :

public static void main(String[] args) throws UnknownHostException {
//获取本地主机ip地址对象。
InetAddress ip = InetAddress.getLocalHost();
//获取其他主机的ip地址对象
ip = InetAddress.getByName("192.168.1.111");
System.out.println(ip.getHostAddress());
System.out.println(ip.getHostName());
}


DNS

域名解析器


UDP传输与接收

Socket就是为网络服务提供的一种机制

通信的两端都有Socket

网络通信其实就是Socket间的通信。

数据在两个Socket间通过IO传输


DatagramSocket与DatagramPacket

建立发送端,接收端。

建立数据包。

调用Soclet的发送接收方法。

关闭Socket

发送端与接收端是两个独立运行的程序。

public class UDPDemo {


/*创建UDP发送端
* 思路:
* 1 建立udp的socket服务。
* 2 将要发送的数据封装到数据包中
* 4 关闭socket服务
* */
public static void main(String[] args) throws IOException {
//1 udpsocket服务,使用DatagramSocket对象
DatagramSocket ds = new DatagramSocket();


//2 将要发送的数据封装到数据包中。
String str = "udp传输演示:哥们来了!";


//使用DatagramPacket将数据封装到该对象包中
byte[] buf = str.getBytes();

/*DatagramPacket(byte[] buf, int length, InetAddress address, int port) 
                  构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。*/
DatagramPacket dp = new DatagramPacket(buf, buf.length,InetAddress.getByName("192.168.1.100"),10000);


//3 通过udp的Socket服务奖数据包发送出去。使用send方法。
ds.send(dp);
//4 关闭资源
ds.close();

}
}

public class UDPReceDemo {
/*建立接收端的思路。
 * 1 建立udp,socket服务,因为是要接受数据,必须要明确一个端口号
 * 2 创建数据包,用于存储接受到的数据,方便用数据包对象的方法解析这些数据。
 * 3 使用socket服务的receive方法接收的数据存储到数据包中。
 * 4 通过数据包的方法解析数据包中的数据。
 * 5 关闭资源。
 * */
public static void main(String[] args) throws IOException {
System.out.println("接收端启动");
//1 建立udp socket服务。
DatagramSocket ds = new DatagramSocket(10000);


//2 创建数据包
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);


//3 使用接收方法将数据存储到数据包中。
ds.receive(dp);//阻塞式的。


//4 通过数据包对象的方法,解析其中的数据,比如,地址,端口,数据内容。
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();//获取端口。
String txt = new String(dp.getData(),0,dp.getLength());
System.out.println(ip+"::"+port+"::"+txt);


//5 关闭资源

ds.close();
}
}

TCP传输

public class ClientDemo {
public static void main(String[] args) throws UnknownHostException, IOException {
/*客户端->服务端
*Tcp传输,客户端建立的过程。
* 1 创建tcp客户端服务器。使用的是Socket对象。
* 建议该对象一创建就明确目的地。要连接的主机。
* 2 如果连接建立成功,说明数据传输通道已建立。
* 该通道就是socke流,是底层建立好的,既然是流,说明这里既有输入
* 又有输出,想要输入或者输出流对象,可以找Socket来获取。
* 可以通过getOutputStream(),和getIntputStream()来获取两个字节流。
* 3 使用输出流,将数据写出。
* 4 关闭资源
* */
//创建客户端
Socket socket = new Socket("192.168.1.100",10002);

//获取socket流中的输出流
OutputStream out = socket.getOutputStream();

//使用输出流将指定的数据写出去。
out.write("tcp演示:哥们又来了!".getBytes());

//读取服务端返回的数据,使用socket读取流。
InputStream in = socket.getInputStream();
byte[] bus = new byte[1024];
int len = in.read(bus);
String str = new String(bus,0,len);
System.out.println(str);

//关闭资源
socket.close();//有这个就不用关流了。
}

}


public class ServerDemo {


public static void main(String[] args) throws IOException {
/*建立tcp服务端的思路:
* 1 创建Socket服务。通过ServerSocket对象
* 2 服务端必须对外提供一个端口,否则客户端换无法连接
* 3 获取连接过来的客户端对象。
* 4 通过客户端对象获取socket流读取客户端发来的数据。。
* 并打印在控制台上
* 5 关闭资源。关客户端,关服务端。
*    
* */
//1 创建服务端对象。
ServerSocket ss = new ServerSocket(10002);

//2 获取连接过来的客户端对象。
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();

//3 通过socket对象获取输入流,要读取客户端发来的数据
InputStream in = s.getInputStream();
byte[] buf = new  byte[1024];
int len = in.read(buf);
String str = new String(buf,0,len);
System.out.println(ip+"::"+str);

//反馈回客户端
OutputStream out = s.getOutputStream();
out.write("收到".getBytes());


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


练习:

文本转换

客户端:

public class TransClient {
public static void main(String[] args) throws UnknownHostException, IOException {
/*思路:
* 客户端:
* 1 需要先有socket端点
* 2 客户端的数据源:键盘。
* 3 客户端的目的:socket
* 4 接收服务端的数据,源:socket
* 5 将数据显示打印出来,目的:控制台。
* 6 在这些流中操作的数据都是文本数据。
* 转换客户端:
* 1 创建socket客户端对象。
* 2 获取键盘录入
* 3 将录入的信息发送给socket输出流。
* */
//1 创建socket客户端对象。
Socket s = new Socket("192.168.1.112",10004);

//2 获取键盘录入
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));

//3 socket输出流
PrintWriter out = new PrintWriter(s.getOutputStream(),true);//输出出去的时候,保持数据 的原样性不变,true 自动刷新
//socket输入流,读取服务端返回的大写数据
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

String line = null;
while((line = buf.readLine())!=null){
if("over".equals(line))
break;
out.println(line);
//读取服务端发回的一行大写数
String upperStr = bufIn.readLine();
System.out.println(upperStr);
}
s.close();//此方法会植入客户端结束标记。从而才能使服务端的readline方法不会一直等待。
}


}


服务端:

public class TransServer {


public static void main(String[] args) throws IOException {
/*转换服端
* 分析:
* 1 serversocket服务
* 2 获取socket对象
* 3 源:socket,读取客户端发过来的需要转换的数据。
* 4 目的:显示在控制台上。
* 5 将数据转成大写发给客户端。
* */
//1 
ServerSocket ss = new ServerSocket(10004);

//2 获取socket对象
Socket s = ss.accept();

//获取ip
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip);

//3 获取socket读取流,并装饰。
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

//获取socket输出流,并装饰
PrintWriter out = new PrintWriter(s.getOutputStream(),true);//true 自动刷新

String line = null;
while((line = bufIn.readLine())!=null){
System.out.println(line);
out.println(line.toUpperCase());
}
s.close();
ss.close();
}


}

常见问题:

基本都是因为阻塞式方法造成的,readLine为阻塞式方法 

在客户端与服务端交互时,使用下列两个方法做结束标记。(缓冲区默认大小1024*8,装满以后自动刷新一次)

 voidshutdownInput()
          此套接字的输入流置于“流的末尾”。 voidshutdownOutput()
          禁用此套接字的输出流。


多线程上传图片:

客户端

public class UploadPicClient {

public static void main(String[] args) throws UnknownHostException, IOException {
Socket s = new Socket("192.168.1.100",10006);
FileInputStream fis = new FileInputStream("0.bmp");
OutputStream out = s.getOutputStream();
byte[] bus = new byte[1024];
int len = 0;
while((len = fis.read(bus))!=-1){
out.write(bus,0,len);
out.flush();
}
s.shutdownOutput();
InputStream ins = s.getInputStream();
byte[] buf = new byte[1024];
int len1 = ins.read(buf);
String str = new String(buf,0,len1);
System.out.println(str);
s.close();
fis.close();
}

}

服务端:

public class UploadPicServer {
public static void main(String[] args) throws IOException {
//创建tcp的socket服务端

ServerSocket ss = new ServerSocket(10006);
while(true){
Socket s = ss.accept();
new Thread(new UploadTask(s)).start();//为每个客户端都建立线程任务
}

}
}

public class UploadTask implements Runnable {
private Socket s;
public UploadTask(Socket s){
this.s = s;
}
public void run() {
int count = 0;
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+"connect...");
try{
InputStream ins = s.getInputStream();
File f = new File("e:\\abc");
if(!f.exists())
f.mkdirs();
File f1 = new File(f,ip+".bmp");
while(f1.exists()){
f1 = new File(f,ip+"("+(++count)+").bmp");
}
FileOutputStream fos = new FileOutputStream(f1);
byte[] bus = new byte[1024];
int len = 0;
while((len = ins.read(bus))!=-1){
fos.write(bus, 0, len);
}
OutputStream out = s.getOutputStream();
out.write("上传成功".getBytes());
fos.close();
s.close();
}catch(IOException e){}

}


}

http: 超文本传输协议

Ftp:文件传输协议

类 URI

表示一个统一资源标识符 (URI) 引用。

类 URL

URL 代表一个统一资源定位符,它是指向互联网“资源”的指针。

构造方法摘要URL(String spec)
          根据 String 表示形式创建 URL 对象。主要方法:

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

openStream

public final InputStream openStream()                             throws IOException
打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream。此方法是下面方法的缩写:
     openConnection().getInputStream()
openConnection
public URLConnection openConnection()                             throws IOException
返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。 

类 URLConnection

方法
 InputStreamgetInputStream()
          返回从此打开的连接读取的输入流。
例:

String str_url = "http://192.168.1.100:8080/myweb/1.html?name=lisi";

URL url = new URL(str_url);

InputStream in = url.openStream();  

相当于:

URLConnection conn = url.openConnection();获取url对象的URL连接器对象,将连接封装成了对象:java中内置的可以解析的具体协议的对象+socket.

InputStream in = conn.getInputStream();

网络架构:

1 C/S  client/server

特点:

该结构的软件,客户端和服务端都需要编写。

开发成本较高,维护较为麻烦

好处:

客户端在本地可以分担一部分运算。

2 B/S   browser/server

特点:

该结构的软件只开发服务器端,不开发客户端,因为客户端直接由浏览器取代。

开发成本相对低,维护更为简单。

缺点:

所有运算都要在服务端完成。

0 0
原创粉丝点击