Java 网络编程
因为需要研究服务器原理,因而复习一下网络编程
TCP 编程
TCP协议在Java中的两个核心对象是
- Socket
- ServerSocket
ServerSocket
ServerSocket
是服务器对象,可以监听自己开放的端口
通过如下方法获取Socket连接
Socket socket = serverSocket.accept();
如果没有人连接,他会一直等待。
Socket
作为客户端需要创建一个Socket对象,然后对服务器进行连接
Socket socket = new Socket("127.0.0.1", 2222);
简单的聊天室
多线程操控,完成多个线程连接服务器,服务器收到通知后再推送给所有线程
服务器端
public class ClientTest {
public InputStream is;
public OutputStream os;
ArrayList<Thread> threads;
public void creatClient(int time) throws IOException, InterruptedException {
Socket socket = new Socket("127.0.0.1", 2222);
os = socket.getOutputStream();
is = socket.getInputStream();
threads = new ArrayList<>();
//复杂发送信息的线程
Thread outThread = new Thread(new Runnable() {
@Override
public void run() {
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(os);
PrintWriter writer = new PrintWriter(outputStreamWriter);
Scanner scanner = new Scanner(System.in);
while (true)
{
String line = scanner.nextLine();
writer.println(line);
writer.flush();
}
}
});
//接收线程
Thread readThread = new Thread(new Runnable() {
@Override
public void run() {
InputStreamReader inputStreamReader = new InputStreamReader(is);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line = "";
try {
while ((line = bufferedReader.readLine())!=null)
{
System.out.println("接收信息");
System.out.println(line);
System.out.println("=========");
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
threads.add(readThread);
threads.add(outThread);
readThread.start();
outThread.start();
//到一定时间关闭程序
Thread.sleep(time);
try {
for (Thread thread : threads) {
thread.stop();
}
os.close();
is.close();
socket.close();
System.out.println("关闭流");
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端
public class ServerTest {
//存放所有socket连接
public static ArrayList<Socket> sockets;
static {
sockets = new ArrayList<>();
}
public static class Client implements Runnable{
Socket socket;
public Client(Socket socket)
{
this.socket = socket;
}
@Override
public void run() {
OutputStream os;
InputStream is = null;
try {
os = socket.getOutputStream();
is = socket.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line = "";
try {
while ((line=reader.readLine())!=null)
{
System.out.println("接收信息 ");
System.out.println(line);
System.out.println("========");
//每次接收到消息都进行广播
for (Socket s : sockets) {
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(s.getOutputStream());
PrintWriter writer = new PrintWriter(outputStreamWriter);
writer.println(line);
writer.flush();
}
}
}catch (Exception e)
{
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
ServerSocket serverSocket = new ServerSocket(2222);
//不断监听
while (true)
{
Socket socket = serverSocket.accept();
sockets.add(socket);
new Thread(new Client(socket)).start();
}
}
}
注意事项
一定要关闭流再结束程序,否则报异常
UDP通信
UPD通信没有名义上的服务器和客户端,都是可以相互发送信息的,信息以包的形式包装
核心对象
DatagramSocket
DatagramPacket
服务器端
//设置发送出去的端口号
DatagramSocket socket = new DatagramSocket(11011);
byte[] bytes = new byte[1024];
//创建发送的数据包
//设置地址,接收端口号
DatagramPacket datagramPacket = new DatagramPacket(bytes,0,bytes.length,InetAddress.getByName("localhost"),9090);
datagramPacket.setData("hello".getBytes());
socket.send(datagramPacket);
客户端
//设置接收端口号
DatagramSocket socket = new DatagramSocket(9090);
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length);
//接收数据
socket.receive(datagramPacket);
byte[] data = datagramPacket.getData();
System.out.println(new String(data));