网络编程的目的是指直接或间接地通过网络协议与其他计算机进行通信。网络编程中有两个主要的问题,一个是如何准确的定位网络上的主机,另一个就是找到主机后如何可靠高效的进行数据传输。
在TCP/IP协议中IP层主要负责网络主机的定位,由IP地址可以唯一地确定Internet上的一台主机。而TCP层则提供面向应用的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据的。
C/S结构(Client /Server)
网络程序的通信双方:一方作为服务器(Server)等待客户(Client)提出请求并予以响应。客户则在需要服务时向服务器提出申请。
服务器一般作为守护进程始终运行,监听网络端口,一旦有客户请求,就会启动一个服务进程来响应该客户,同时自己继续监听服务端口,使后来的客户也能及时得到服务。
网络基础知识
IP地址:标识计算机等网络设备的网络地址,由四个8位的二进制数组成
主机名(hostname):网络地址的助记名,按照域名进行分级管理。如:www.sina.com.cn。
端口号(port):网络通信时同一机器上的不同进程(运行的程序)的标识。
服务类型(service):网络的各种服务,它们使用不同的端口号。如:http(80), telnet(23), ftp(21), smtp(25)。
通常一台主机上总是有很多个进程需要网络资源进行网络通讯。网络通讯的对象准确的讲不是主机,而应该是主机中运行的进程。这时候光有主机名或IP地址来标识这么多个进程显然是不够的。端口号就是为了在一台主机上提供更多的网络资源而采取得一种手段,也是TCP层提供的一种机制。只有通过主机名或IP地址和端口号的组合才能唯一的确定网络通信中的进程。
服务类型(Service)是那些已经被标准化了的网络应用(如HTTP、FTP等等)。程序员可以编写自己的基于网络的服务器,但不能被称作标准的服务类型,也不能使用被标准服务类型占用的端口号。
端口号为一个0~65535之间的整数,而0~1023已被系统预先占用,程序员编写网络程序应使用1024~65535的端口来进行通信。
编写TCP的网络程序
建立客户与服务器之间的连接:指的是客户进程与服务器进程之间的逻辑连接,用Socket(套接字)实现。
实现客户与服务器之间的通信:指的是客户进程与服务器进程之间的数据传递,用Socket的流对象实现。
使用Socket进行TCP网络编程,一般包含以下四个基本步骤:
(1)创建Socket,实现连接;
(2)打开连接到Socket的输入/输出流;
(3)对Socket进行读/写操作;
(4)关闭Socket。
附:一个简单的TCP通信Demo:
//server.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
try {
ServerSocket s = new ServerSocket(9000);
System.out.println("服务已经开启,等待客户来访问!");
Socket socket = s.accept();//阻塞方法
System.out.println("接受到"+socket.getInetAddress().getHostAddress()+"的访问!");
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
BufferedReader br1 = new BufferedReader(
new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);
while(true){
String str = br.readLine();//从socket的管道中读客户端发过来的数据
System.out.println(str);//打印到控制台
String str1 = br1.readLine();//从键盘读数据
if("exit".equals(str1))break;
pw.println(str1);//写给客户端 写到socket的管道里
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//Client.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1",9000);
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);
BufferedReader br1 = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
while(true){
String str = br.readLine();//从客户端键盘读数据
if("exit".equals(str))break;
pw.println(str);//写给服务器 写到了socket得管道里
String str1 = br1.readLine();//从socket管道里读服务端发过来的数据
System.out.println(str1);//打印到控制台
}
} catch (Exception e) {
e.printStackTrace();
}
}
}