1,网络基础和软件编程
软件编写人员不需要了解太多的网络知识(基础还是需要的);软件编写人员主要抓住几点就可以做网络编程;
1,信息传输都是0和1的传输;
2,信息传输需要遵照网络协议;(底存的网络协议 和传输格式协议)
3,抓住传输协议的要点(如 协议的用途 简要协议实现方式)
4,IO
注:有很软件编程人员通常都不知道什么是协议,抓不到协议重点;有些时候在对接的时候问他们使用的什么协议,统一回复tcp/ip协议;这让我很是蛋疼;
补充:OSI(Open System Interconnection)开放式互联协议模型
分为7层:1.物理层 2.数据链路层 3.网络层 4.传输层 5.会话层 6.表示层 7.应用层
TCP/IP协议模型:
分为4层: 1.网络接口层,2.互联网层 3.传输层 4.应用层
协议都是分层的,我们常用的都是应用层协议;如htpp协议;
什么是协议?协议规定了我们在网络传输中的格式样板;
2,Java网络编程Socket
1,什么是Socket
网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定。
但是,Socket所支持的协议种类也不光TCP/IP一种,因此两者之间是没有必然联系的。在Java环境下,Socket编程主要是指基于TCP/IP协议的网络编程。
2,Socket通讯的过程
Server端Listen(监听)某个端口是否有连接请求,Client端向Server 端发出Connect(连接)请求,Server端向Client端发回Accept(接受)消息。一个连接就建立起来了。Server端和Client 端都可以通过Send,Write等方法与对方通信。
对于一个功能齐全的Socket,都要包含以下基本结构,其工作过程包含以下四个基本的步骤:
(1) 创建Socket;
(2) 打开连接到Socket的输入/出流;
(3) 按照一定的协议对Socket进行读/写操作;
(4) 关闭Socket.(在实际应用中,并未使用到显示的close,虽然很多文章都推荐如此,不过在我的程序中,可能因为程序本身比较简单,要求不高,所以并未造成什么影响。)
3,创建Socket
创建Socket
java在包java.net中提供了两个类Socket和ServerSocket,分别用来表示双向连接的客户端和服务端。这是两个封装得非常好的类,使用很方便。其构造方法如下:
Socket(InetAddress address, int port);
Socket(InetAddress address, int port, boolean stream);
Socket(String host, int prot);
Socket(String host, int prot, boolean stream);
Socket(SocketImpl impl)
Socket(String host, int port, InetAddress localAddr, int localPort)
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
ServerSocket(int port);
ServerSocket(int port, int backlog);
ServerSocket(int port, int backlog, InetAddress bindAddr)
其中address、host和port分别是双向连接中另一方的IP地址、主机名和端 口号,stream指明socket是流socket还是数据报socket,localPort表示本地主机的端口号,localAddr和 bindAddr是本地机器的地址(ServerSocket的主机地址),impl是socket的父类,既可以用来创建serverSocket又可 以用来创建Socket。count则表示服务端所能支持的最大连接数。例如:学习视频网 http://www.xxspw.com
Socket client = new Socket("127.0.01.", 80);
ServerSocket server = new ServerSocket(80);
注意,在选择端口时,必须小心。每一个端口提供一种特定的服务,只有给出正确的端口,才 能获得相应的服务。0~1023的端口号为系统所保留,例如http服务的端口号为80,telnet服务的端口号为21,ftp服务的端口号为23, 所以我们在选择端口号时,最好选择一个大于1023的数以防止发生冲突。
在创建socket时如果发生错误,将产生IOException,在程序中必须对之作出处理。所以在创建Socket或ServerSocket是必须捕获或抛出例外。
package com.dom.socket;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServiceDom {
public static void main(String[] args){
try {
ServerSocket server = new ServerSocket(8082);
Socket socket = server.accept();
//获得服务端套接字的输入输出流
Reader reader = new InputStreamReader(socket.getInputStream());
char chars[] = new char[64];
int len;
StringBuilder sb = new StringBuilder();
while ((len=reader.read(chars)) != -1) {
sb.append(new String(chars, 0, len));
}
System.out.println("from client: " + sb);
reader.close();
socket.close();
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.dom.socket;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientDom {
public static void main(String [] ags){
try {
Socket socket = new Socket("127.0.0.1",8082);
Writer writer = new OutputStreamWriter(socket.getOutputStream());
writer.write("my socket dom");
writer.flush();
writer.close();
socket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
使用socket实现http协议传输消息
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
/**
* 一个简单的HTTP客户端,发送HTTP请求,模拟浏览器
* 可打印服务器发送过来的HTTP消息
*/
public class SimpleHttpClient {
private static String encoding = "GBK";
public static void main(String[] args) {
try {
Socket s = new Socket(InetAddress.getLocalHost(), 8080);
OutputStreamWriter osw = new OutputStreamWriter(s.getOutputStream());
StringBuffer sb = new StringBuffer();
sb.append("GET /HttpStream/gb2312.jsp HTTP/1.1\r\n");
sb.append("Host: localhost:8088\r\n");
sb.append("Connection: Keep-Alive\r\n");
sb.append("\r\n");
osw.write(sb.toString());
osw.flush();
//--输出服务器传回的消息的头信息
InputStream is = s.getInputStream();
String line = null;
int contentLength = 0;//服务器发送回来的消息长度
// 读取所有服务器发送过来的请求参数头部信息
do {
line = readLine(is, 0);
//如果有Content-Length消息头时取出
if (line.startsWith("Content-Length")) {
contentLength = Integer.parseInt(line.split(":")[1].trim());
}
//打印请求部信息
System.out.print(line);
//如果遇到了一个单独的回车换行,则表示请求头结束
} while (!line.equals("\r\n"));
//--输消息的体
System.out.print(readLine(is, contentLength));
//关闭流
is.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/*
* 这里我们自己模拟读取一行,因为如果使用API中的BufferedReader时,它是读取到一个回车换行后
* 才返回,否则如果没有读取,则一直阻塞,直接服务器超时自动关闭为止,如果此时还使用BufferedReader
* 来读时,因为读到最后一行时,最后一行后不会有回车换行符,所以就会等待。如果使用服务器发送回来的
* 消息头里的Content-Length来截取消息体,这样就不会阻塞
*
* contentLe 参数 如果为0时,表示读头,读时我们还是一行一行的返回;如果不为0,表示读消息体,
* 时我们根据消息体的长度来读完消息体后,客户端自动关闭流,这样不用先到服务器超时来关闭。
*/
private static String readLine(InputStream is, int contentLe) throws IOException {
ArrayList lineByteList = new ArrayList();
byte readByte;
int total = 0;
if (contentLe != 0) {
do {
readByte = (byte) is.read();
lineByteList.add(Byte.valueOf(readByte));
total++;
} while (total < contentLe);//消息体读还未读完
} else {
do {
readByte = (byte) is.read();
lineByteList.add(Byte.valueOf(readByte));
} while (readByte != 10);
}
byte[] tmpByteArr = new byte[lineByteList.size()];
for (int i = 0; i < lineByteList.size(); i++) {
tmpByteArr[i] = ((Byte) lineByteList.get(i)).byteValue();
}
lineByteList.clear();
return new String(tmpByteArr, encoding);
}
}
上面都是采用的是io;因为NIO的缘故 这些代码都不是自己写的;后面准备自己写NIO的实现;(就这一点东东就花了了我一天时间 真心伤不起呀;基础 基础 基础夯实真的很重要) 在此记录以备后用
来源:oschina
链接:https://my.oschina.net/u/1249631/blog/395872