简易网络聊天编程
1、网络通信两要素
-
IP地址、端口
-
6ipconfig->获取本机地址;
-
ping www.baidu.com->获取对方IP地址
-
-
网络通信协议--TCP&UDP
2、IP地址
-
IPv4:地址是4位字节,截至2011年已经分完,北美大概30亿,亚洲4亿;
-
IPv6:地址是8位字节,尚未完成布置
-
import java.net.InetAddress;
import java.net.UnknownHostException;
public class TestNetAdress {
public static void main(String[] args) throws UnknownHostException {
//查询本机IP地址
InetAddress inetAddress1 = InetAddress.getByName("192.168.0.127");
System.out.println(inetAddress1);
InetAddress inetAddress2 = InetAddress.getByName("localhost");
System.out.println(inetAddress2);
InetAddress inetAddress3 = InetAddress.getLocalHost();
System.out.println(inetAddress3);
//查询网站IP地址
InetAddress inetAddress4 = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress4);
//常用的方法
System.out.println(inetAddress4.getAddress());//返回的是byte
System.out.println(inetAddress4.getHostAddress());//返回的是域名地址
System.out.println(inetAddress4.getHostName());//返回的是域名
System.out.println(inetAddress4.getCanonicalHostName());//返回规范名字
}
}
3、端口
-
端口:代表计算机上某一进程,被规定0~65535,查看端口:netstat -ano
-
TCP、UDP:65535*2,TCP:80,UDP:80,单个协议下,端口号不能冲突
-
-
端口分类:
-
公有端口0~1023
-
HTTP端口:80 ->www.baidu.com == http://www.baidu.com:80/
-
HTTPS端口:443 ->www.baidu.com == https://www.baidu.com:443/
-
FTP:21
-
TELENT:23
-
-
程序注册端口:1024~49151,分配用户或程序
-
Tomcat:8080
-
Mysq:3306
-
Oracal:1521
-
-
动态、私有:49152~65535
-
-
netstat -ano #查看端口
netstat -ano|findstr "9048" #查看指定端口,双引号前面有空格
tasklist|findstr "9504" #查看指定端口
ctrl + shift + esc//创建地址和端口
import java.net.InetSocketAddress;
public class TestInetSocketsAddresses {
public static void main(String[] args) {
InetSocketAddress socketAddress
= new InetSocketAddress("192.168.0.127", 8080);//创建地址和端口
InetSocketAddress socketAddress2
= new InetSocketAddress("localhost", 8080);
System.out.println(socketAddress);
System.out.println(socketAddress2);
System.out.println(socketAddress2.getAddress());//获取用户地址
System.out.println(socketAddress2.getHostName());//获取用户名
System.out.println(socketAddress2.getPort());//获取端口
}
}
4、通信协议
-
TCP对比UDP
-
TCP:类似打电话;连接稳定,三次握手,四次挥手;客户端和服务器;连接稳定,释放连接,效率低。
-
UDP:类似发短信,不连接,不稳定,只是把包丢出去就不管了;
-
-
5、TCP实现聊天
-
TCP
-
TCP类似打电话,连接稳定,三次握手,四次挥手
-
UDP类似发短信,不连接,不稳定,只是把包丢出去就不管了
-
-
package network.tcptalk;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
//客户端----------------------------------
public class TcpClientDemo01 {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
try {
//客户端要知道服务端的地址,端口号
InetAddress serverIP = InetAddress.getByName("192.168.0.107");//本机的地址ipconfig
int port = 9999;
//创建一个socket连接
socket = new Socket(serverIP, port);
//发送消息流IO
os = socket.getOutputStream();//用于将字节写入此套接字的输出流。
os.write("你好呀!".getBytes());//字符串转为字节,再写入输出流
} catch (Exception e) {
e.printStackTrace();
}finally {
if(os!=null){//确保程序运行
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket!=null){//确保程序运行
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
package network.tcptalk;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务端-------------------------------------
public class TcpServerDemo01 {
public static void main(String[] args) {
ServerSocket serversocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos =null;
try {
//1、服务端先有一个地址
serversocket = new ServerSocket(9999);
//2、等待连接
socket = serversocket.accept();
//读取客户端消息
is = socket.getInputStream();
//3、管道流,read读输入管道->存入buffer缓存->write写入输出管道
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];//字节缓存容器
int len;
while((len= is.read(buffer))!=-1){//从输入流读取字节存入buffer,再判断是否读完输入流,读完输入流则返回-1
baos.write(buffer,0,len);//将buffer里面的字节写入输出管道
}
System.out.println(baos.toString());//将字节转成字符串打印输出
} catch (IOException e) {
e.printStackTrace();
}finally {
if(baos!=null){//抛出异常,确保程序不崩溃不为空才需要主动关闭,为空就自动关闭了
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(serversocket!=null){
try {
serversocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
6、文件传输
-
//客户端
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class TcpFileClient {
public static void main(String[] args) throws Exception {
//获取服务器端口地址
InetAddress serverIP = InetAddress.getByName("192.168.0.107");
int port = 9900;
//创建一个socket连接
Socket socket = new Socket(serverIP,port);
//创建一个输出流
OutputStream os = socket.getOutputStream();
//创建文件输出流,图片文件要放在根目录
FileInputStream fis = new FileInputStream(new File("Guilinlandscape.jpg"));
//这一段保证数据不出错,不出现乱码
int len;
byte[] buffer = new byte[1024];
while((len=fis.read(buffer))!=-1){
os.write(buffer,0,len);
}
//告诉接口我已经输出完毕
socket.shutdownOutput();
//接收服务器传过来的消息
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len2;
byte[] buffer2 = new byte[1024];
while((len2=is.read(buffer2))!=-1){
baos.write(buffer2,0,len2);
}
System.out.println(baos.toString());
baos.close();
is.close();
fis.close();
os.close();
socket.close();
}
} -
//服务端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpFileServer {
public static void main(String[] args) throws IOException {
//创建服务器地址端口
ServerSocket serversocket = new ServerSocket(9900);
//等待连接
Socket socket = serversocket.accept();
//创建输入流,这一段是防止传输的数据出错
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
int len;
byte[] buffer = new byte[1024];
while((len=is.read(buffer))!=-1){
fos.write(buffer,0,len);
}
//返回文件接收成功给客户端
OutputStream os = socket.getOutputStream();
os.write("文件传输完毕!".getBytes());
fos.close();
is.close();
socket.close();
serversocket.close();
}
}
7、UDP聊天
-
//发送端
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.*;
public class UdpChatSender {
public static void main(String[] args) throws Exception {
//建立端口
DatagramSocket socket = new DatagramSocket(8888);
InetSocketAddress localhost = new InetSocketAddress("localhost", 6666);
//准备发送数据,读到的是字符串
while(true){
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String data = reader.readLine();
byte[] sendData = data.getBytes();
//建立发送包,
DatagramPacket packet = new DatagramPacket(sendData,0,sendData.length,localhost);
//发送包
socket.send(packet);
if(data.equals("bye")){
break;
}
}
socket.close();
}
}
-
//接收端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UdpChatReceiver {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(6666);
while(true){
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
socket.receive(packet);
//打印出接收到的数据
byte[] data = packet.getData();
String dataToString = new String(data,0, data.length);
if(dataToString.equals("bye")){//有问题
System.out.println("结束!");
break;
}
System.out.println(dataToString);
}
socket.close();
}
}
8、UDP多线程聊天
-
//发送端
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
public class TalkSend implements Runnable{
DatagramSocket socket = null;
BufferedReader reader = null;
private int fromPort;
private String toIp;
private int toPort;
public TalkSend( int fromPort, String toIp, int toPort) {
this.fromPort = fromPort;
this.toIp = toIp;
this.toPort = toPort;
try {
socket = new DatagramSocket(fromPort);
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
-
//接收端
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class TalkReceive implements Runnable{
DatagramSocket socket = null;
private int port;
private String msgFrom;
public TalkReceive(int port,String msgFrom) {
this.port = port;
this.msgFrom = msgFrom;
try {
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
//聊天用户二
public class TalkTalkerTwo {
public static void main(String[] args) {
new Thread(new TalkSend(5555,"localhost",6666)).start();
new Thread(new TalkReceive(8888,"One")).start();
}
}//聊天用户一
public class TalkTalkerOne {
public static void main(String[] args) {
new Thread(new TalkSend(4444,"localhost",8888)).start();
new Thread(new TalkReceive(6666,"Two")).start();
}
}
-
浙公网安备 33010602011771号