Socket
- 据交换,这个双向连接的一端称为一个Socket
- java.net包中定义的两个类Socket和ServerSocket,分别用来实现双向连接的client和server端
- 建立连接时所需的寻址信息为远程计算机的ip地址和端口号(Port number)
//Server端
import java.net.*;
import java.io.*;
public class TcpServer {
public static void main(String[] args) throws Exception{
ServerSocket ss = new ServerSocket(6666);
while(true) {
Socket s = ss.accept();
DataInputStream dis = new DataInputStream(s.getInputStream());
System.out.println(dis.readUTF());
dis.close();
s.close();
}
}
}
//Client端
import java.io.*;
import java.net.*;
public class TcpClient {
public static void main(String[] args) throws Exception{
Socket s = new Socket("127.0.0.1",6666);
OutputStream os = s.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF("Hello Server");
dos.flush();
dos.close();
}
}
首先说Server端,Server端用的类是ServerSocket,构造方法中的参数表示监听哪个端口,一个服务器或者一台电脑上有很多端口,其中有一些是已经被占用的,就不能用,这里我随便用6666这个端口
然后是Client端,Client端用的类是Socket,构造方法中的两个参数,第一个是访问的ip,127.0.0.1代表的ip表示本机,也可以用localhost替换,第二个参数代表访问Server端的哪个端口
随后Client端通过流,向Server端发送消息,Server端调用accept方法首先允许Client端访问,然后也通过流读入Client发送的消息,整个过程是个死循环,模拟真实服务器24小时不间断的操作
//Server端
import java.net.*;
import java.io.*;
public class TestServer {
public static void main(String[] args) {
try {
ServerSocket s = new ServerSocket(6666);
while(true) {
Socket s1 = s.accept();
OutputStream os = s1.getOutputStream();
DataOutputStream dos =
new DataOutputStream(os);
dos.writeUTF("Hello," + s1.getInetAddress() + ",Port#" + s1.getPort());
dos.close();
s1.close();
}
}catch (IOException e) {
e.printStackTrace();
System.out.println("程序运行错误:" + e);
}
}
}
//Client端
import java.io.*;
import java.net.*;
public class TestClient {
public static void main(String[] args) {
try {
Socket s = new Socket("localhost",6666);
InputStream is = s.getInputStream();
DataInputStream dis =
new DataInputStream(is);
System.out.println(dis.readUTF());
dis.close();
s.close();
}catch(IOException e) {
e.printStackTrace();
System.out.println("服务器连接超时" + e);
}
}
}
上面的程序不再是Client向Server端发送消息,而是Server端向Client端发送消息,在Server端中输出代码里,有一个方法getInetAddress,这个返回的不是Serveer端的ip,返回的是Client端的IP
其次,getPort方法返回的是Client出来的端口号,Client使用哪个端口是系统随机分配的,而Server端开发什么端口是自定义的,这两个有区别
//Server端
import java.net.*;
import java.io.*;
public class TestSocketServer {
public static void main(String[] args) {
InputStream in = null;
OutputStream out = null;
try {
ServerSocket s = new ServerSocket(6666);
Socket s1 = s.accept();
in = s1.getInputStream();
out = s1.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
DataInputStream dis = new DataInputStream(in);
String ss = null;
if((ss = dis.readUTF()) != null) {
System.out.println(s);
System.out.println("from:" + s1.getInetAddress());
System.out.println("Port:" + s1.getPort());
}
dos.writeUTF("Hello");
dis.close();
dos.close();
s1.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
//Client端
import java.net.*;
import java.io.*;
public class TestSocketClient {
public static void main(String[] args) {
InputStream is = null;
OutputStream os = null;
try {
Socket s = new Socket("localhost",6666);
is = s.getInputStream();
os = s.getOutputStream();
DataInputStream dis = new DataInputStream(is);
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF("hey");
String ss = null;
if((ss = dis.readUTF()) != null) {
System.out.println(ss);
}
dis.close();
dos.close();
s.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
上面的程序实现了Server和Client相互传输信息
聊天小程序
import java.net.*;
import java.io.*;
public class TalkServer {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(6666);
Socket socket = server.accept();
String line = null;
BufferedReader br =
new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter pw =
new PrintWriter(socket.getOutputStream());
BufferedReader br1 =
new BufferedReader(
new InputStreamReader(System.in));
System.out.println("Client:" + br.readLine());
line = br1.readLine();
while(!line.equals("exit")) {
pw.println(line);
pw.flush();
System.out.println("Server:" + line);
System.out.println("Client:" + br.readLine());
line = br1.readLine();
}
br.close();
br1.close();
pw.close();
server.close();
socket.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
import java.net.*;
import java.io.*;
public class TalkClient {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost",6666);
BufferedReader br =
new BufferedReader(
new InputStreamReader(System.in));
PrintWriter pw =
new PrintWriter(socket.getOutputStream());
BufferedReader br1 =
new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String readLine;
readLine = br.readLine();
while(!readLine.equals("exit")){
pw.println(readLine);
pw.flush();
System.out.println("Client:" + readLine);
System.out.println("Server:" + br1.readLine());
readLine = br.readLine();
}
br.close();
br1.close();
pw.close();
socket.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
补充
accept和readUTF方法是阻塞式的,也就是说如果没有Client向Server端发送消息或者访问端口,Server就会一直等待,不会执行下面的语句
1
?