Socket
A. 两个Java应用程序可通过一个双向的网络通信连接实现数据交换,这个双向链路的一端称为一个Socket
B. Socket通常用来实现client-server连接
C. Java.net包中定义的两个类Socket和ServerSocket,分别用来实现双向连接的client和server端
D. 建立连接时所需要的寻址信息为远程计算机的IP地址和端口号(Port number)
IP地址,端口号。端口号在计算机内部是用两个字节来表示,也就是说总共有65536个端口。在这儿需要注意下面两个点:
•1.1024之前的端口我们自己编的程序不要征用它,因为这些端口是给系统用的。
•2.TCP端口和UDP端口是分开的,比如说TCP有个8888端口,他和你的UDP8888端口是不一样的。
•3.上述每一类有65536个端口。
既然要实现通信,那我们肯定要确定两个通信对象,一个是服务器对象server,一个是客户端对象client。我们需要知道,这两个对象是两个应用程序,他们的对话,是两个不同的程序之间的对话。你会说我只有两个对象也还没法实现他们之间的交互啊,不用急,我也知道他们两个不是神仙会心有灵犀。两个对象之间想要实现互相之间的信息交互,就必须要有一个通道。这个通道就像是一根管子,一头扎在服务器端,一头插在客户端。信息就在这根管子里来来往往。这根管子怎么插呢,插在哪儿呢?这个时候就需要用到刚刚提到的Socket了。
Socket的意思呢就是一个插座,服务器和客户端各有一个插座,安插在各自的一个端口上,管子插在这两个插座上,然后在他们这两个端口上接入数据流。Socket通常用来实现server-client连接。Java里面有一个包java.net,他下边有定义了两个类,Socket和ServerSocket,分别用来实现双向连接的server端和client端。
接下来建立TCP服务器端和客户端。
服务器端:我们用的是ServerSocket,新建一个server插座,并且交给他一个端口号,这个插座他有一个非常方便的构造方法ServerSocket(int port),让他知道自己监听哪一个端口,然后新建一个socket对象,开机,并用.accept语句让他处在待机状态,等待接受client的接入。一旦有客户端接入就将它赋给新建的Socket对象,并且用.getInputStream以及.getOutputStream命令获得他的输入输出流。这个流,就是一根管子,信息都在这根管子里流通。这样说东西不怎么好说,那么我们就在这个流上面再包一层,将这个流封装成DataOutputStream(),DataInputStream。然后就可以利用输出流(这个是相对于服务器来说,这个输出流到了客户端就成了输入流了)来.write信息,利用输入流来.read()获取客户端发来的信息。Ok,接收完了,.close关闭输入输出流,以及关闭socket,关机。
服务端线程处理类/tcp
A. 两个Java应用程序可通过一个双向的网络通信连接实现数据交换,这个双向链路的一端称为一个Socket
B. Socket通常用来实现client-server连接
C. Java.net包中定义的两个类Socket和ServerSocket,分别用来实现双向连接的client和server端
D. 建立连接时所需要的寻址信息为远程计算机的IP地址和端口号(Port number)
IP地址,端口号。端口号在计算机内部是用两个字节来表示,也就是说总共有65536个端口。在这儿需要注意下面两个点:
•1.1024之前的端口我们自己编的程序不要征用它,因为这些端口是给系统用的。
•2.TCP端口和UDP端口是分开的,比如说TCP有个8888端口,他和你的UDP8888端口是不一样的。
•3.上述每一类有65536个端口。
既然要实现通信,那我们肯定要确定两个通信对象,一个是服务器对象server,一个是客户端对象client。我们需要知道,这两个对象是两个应用程序,他们的对话,是两个不同的程序之间的对话。你会说我只有两个对象也还没法实现他们之间的交互啊,不用急,我也知道他们两个不是神仙会心有灵犀。两个对象之间想要实现互相之间的信息交互,就必须要有一个通道。这个通道就像是一根管子,一头扎在服务器端,一头插在客户端。信息就在这根管子里来来往往。这根管子怎么插呢,插在哪儿呢?这个时候就需要用到刚刚提到的Socket了。
Socket的意思呢就是一个插座,服务器和客户端各有一个插座,安插在各自的一个端口上,管子插在这两个插座上,然后在他们这两个端口上接入数据流。Socket通常用来实现server-client连接。Java里面有一个包java.net,他下边有定义了两个类,Socket和ServerSocket,分别用来实现双向连接的server端和client端。
接下来建立TCP服务器端和客户端。
服务器端:我们用的是ServerSocket,新建一个server插座,并且交给他一个端口号,这个插座他有一个非常方便的构造方法ServerSocket(int port),让他知道自己监听哪一个端口,然后新建一个socket对象,开机,并用.accept语句让他处在待机状态,等待接受client的接入。一旦有客户端接入就将它赋给新建的Socket对象,并且用.getInputStream以及.getOutputStream命令获得他的输入输出流。这个流,就是一根管子,信息都在这根管子里流通。这样说东西不怎么好说,那么我们就在这个流上面再包一层,将这个流封装成DataOutputStream(),DataInputStream。然后就可以利用输出流(这个是相对于服务器来说,这个输出流到了客户端就成了输入流了)来.write信息,利用输入流来.read()获取客户端发来的信息。Ok,接收完了,.close关闭输入输出流,以及关闭socket,关机。
客户端:写法和服务器端有点类似,新建一个插座,这儿需要留意的是,客户端需要用到的插座是Socket而不是ServerSocket,新建一个Socket牌插座,同样用他的Socket(String host,int port)构造方法方法给他一个IP地址和端口号,让它拨打区号以及具体电话号,这个和服务器端的IP地址以及端口号要一致,ok,这个时候server就相当于申请连接到服务器的某一个端口上了。两个程序就等于是连接上了。但是有些人就会问了啊,这只是客户端申请连接,人家服务器接不接受呢。好,前面我们的服务器不是提到了.accept么,这个方法就是用来接受客户端的,这个时候就是:你申请连接,我接受连接,接下来,照着上面服务器一样,客户端也获取到自己的输入输出流,封装,用输出流写出信息。咱们之间就可以互相通信了。还有一个问题啊,要是如果有另一个客户端接入了呢?简单,那就再.accept一下。如果有N多客户端接入,那就不断的.accept,不断循环它。可以用while语句。也可以引入多线程。
客户端/tcp
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/*
* 客户端
*/
public class Client {
public static void main(String[] args) {
try {
//1.创建客户端Socket,指定服务器地址和端口
Socket socket=new Socket("localhost", 8888);
//2.获取输出流,向服务器端发送信息
OutputStream os=socket.getOutputStream();//字节输出流
PrintWriter pw=new PrintWriter(os);//将输出流包装为打印流
pw.write("用户名:alice;密码:789");
pw.flush();
socket.shutdownOutput();//关闭输出流
//3.获取输入流,并读取服务器端的响应信息
InputStream is=socket.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(is));
String info=null;
while((info=br.readLine())!=null){
System.out.println("我是客户端,服务器说:"+info);
}
//4.关闭资源
br.close();
is.close();
pw.close();
os.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务端/tcp
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
/*
* 基于TCP协议的Socket通信,实现用户登陆
* 服务器端
*/
public class Server {
public static void main(String[] args) {
try {
//1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
ServerSocket serverSocket=new ServerSocket(8888);
Socket socket=null;
//记录客户端的数量
int count=0;
System.out.println("***服务器即将启动,等待客户端的连接***");
//循环监听等待客户端的连接
while(true){
//调用accept()方法开始监听,等待客户端的连接
socket=serverSocket.accept();
//创建一个新的线程
ServerThread serverThread=new ServerThread(socket);
//启动线程
serverThread.start();
count++;//统计客户端的数量
System.out.println("客户端的数量:"+count);
InetAddress address=socket.getInetAddress();
System.out.println("当前客户端的IP:"+address.getHostAddress());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务端线程处理类/tcp
mport java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
/*
* 服务器线程处理类
*/
public class ServerThread extends Thread {
// 和本线程相关的Socket
Socket socket = null;
public ServerThread(Socket socket) {
this.socket = socket;
}
//线程执行的操作,响应客户端的请求
public void run(){
InputStream is=null;
InputStreamReader isr=null;
BufferedReader br=null;
OutputStream os=null;
PrintWriter pw=null;
try {
//获取输入流,并读取客户端信息
is = socket.getInputStream();
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
String info=null;
while((info=br.readLine())!=null){//循环读取客户端的信息
System.out.println("我是服务器,客户端说:"+info);
}
socket.shutdownInput();//关闭输入流
//获取输出流,响应客户端的请求
os = socket.getOutputStream();
pw = new PrintWriter(os);
pw.write("欢迎您!");
pw.flush();//调用flush()方法将缓冲输出
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//关闭资源
try {
if(pw!=null)
pw.close();
if(os!=null)
os.close();
if(br!=null)
br.close();
if(isr!=null)
isr.close();
if(is!=null)
is.close();
if(socket!=null)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服务端/udp
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/*
* 服务器端,实现基于UDP的用户登陆
*/
public class UDPServer {
public static void main(String[] args) throws IOException {
/*
* 接收客户端发送的数据
*/
//1.创建服务器端DatagramSocket,指定端口
DatagramSocket socket=new DatagramSocket(8800);
//2.创建数据报,用于接收客户端发送的数据
byte[] data =new byte[1024];//创建字节数组,指定接收的数据包的大小
DatagramPacket packet=new DatagramPacket(data, data.length);
//3.接收客户端发送的数据
System.out.println("****服务器端已经启动,等待客户端发送数据");
socket.receive(packet);//此方法在接收到数据报之前会一直阻塞
//4.读取数据
String info=new String(data, 0, packet.getLength());
System.out.println("我是服务器,客户端说:"+info);
/*
* 向客户端响应数据
*/
//1.定义客户端的地址、端口号、数据
InetAddress address=packet.getAddress();
int port=packet.getPort();
byte[] data2="欢迎您!".getBytes();
//2.创建数据报,包含响应的数据信息
DatagramPacket packet2=new DatagramPacket(data2, data2.length, address, port);
//3.响应客户端
socket.send(packet2);
//4.关闭资源
socket.close();
}
}
客户端/udp
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
/*
* 客户端
*/
public class UDPClient {
public static void main(String[] args) throws IOException {
/*
* 向服务器端发送数据
*/
//1.定义服务器的地址、端口号、数据
InetAddress address=InetAddress.getByName("localhost");
int port=8800;
byte[] data="用户名:admin;密码:123".getBytes();
//2.创建数据报,包含发送的数据信息
DatagramPacket packet=new DatagramPacket(data, data.length, address, port);
//3.创建DatagramSocket对象
DatagramSocket socket=new DatagramSocket();
//4.向服务器端发送数据报
socket.send(packet);
/*
* 接收服务器端响应的数据
*/
//1.创建数据报,用于接收服务器端响应的数据
byte[] data2=new byte[1024];
DatagramPacket packet2=new DatagramPacket(data2, data2.length);
//2.接收服务器响应的数据
socket.receive(packet2);
//3.读取数据
String reply=new String(data2, 0, packet2.getLength());
System.out.println("我是客户端,服务器说:"+reply);
//4.关闭资源
socket.close();
}
}