InetAddress ip=InetAddress.getByName("127.0.0.1");
常见的tcp协议的软件 :
Netcat: nc yum install nc
Telnet:
TCP:用来实现双向安全连接网络通信
Socket通信模型:
进行网络通信时,Socket需要借助数据流来完成数据的传递工作
TCP:面向连接的网络通讯(在传输数据之前,需要提前建立连接通道)
一个客户端对应一个服务器端
服务器端:
客户端:
打成jar包,运行两个客户端对服务器进行传输数据,无法收到第二个的数据;
public class TCPServer {
//多线程
//姓名=》socket Map集合存储 key/value
public static HashMap onlineUsers = new HashMap();
public static void main(String[] args) {
try {
ServerSocket serverSocket=new ServerSocket(18888);//创建绑定到特定端口的服务器套接字。
System.out.println("start!");
while (true) {
Socket socket = serverSocket.accept();// 侦听并接受到此套接字的连接。socket接受serversocket的socket对象;一个socket对应一个客户端
Worker worker = new Worker(socket);
worker.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Worker extends Thread {
private Socket socket;
Worker(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream inputStream = socket.getInputStream();//返回此套接字的输入流。
byte[] b = new byte[1024];
while (true) {
int p = inputStream.read(b);
String info = new String(b, 0, p);
if (!info.trim().equals(""))
System.out.println("数据:" + info);
receive(info);//报文分析and发送返回信息
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void receive(String info) {
try {
// System.out.println(info);
// OutputStream outputStream = socket.getOutputStream();
String[] s = info.split("-");
if (s[1].equals("login")) {
TCPServer.onlineUsers.put(s[2], socket);
sendMessage(s[2],"登录成功");
} else if (s[1].equals("logout")) {
sendMessage(s[2], "注消完毕");
TCPServer.onlineUsers.remove(s[2]);
} else if (s[1].equals("onlineusers")) {
String names = "";
for (Map.Entry entry : TCPServer.onlineUsers.entrySet()) {
names += entry.getKey() + "-";
}
sendMessage(s[2],("message-onlineusers-" + names));
}
if (s[0].equals("message")) {
String s1=s[1]+":"+s[3];
for (Map.Entry entry : TCPServer.onlineUsers.entrySet()){
if(entry.getKey().equals(s[2]))
sendMessage(s[2],s1);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
//返回信息
public void sendMessage(String name, String info){
Socket socket = TCPServer.onlineUsers.get(name);
try{
OutputStream outputStream = socket.getOutputStream();
outputStream.write(info.getBytes());
outputStream.flush();
}catch (Exception e){
e.printStackTrace();
}
}
}
public class TCPkehu {
//多线程
public static void main(String[] args) {
try {
Scanner scanner = new Scanner(System.in);
Socket socket=new Socket("10.0.18.88",18888);
//收消息
Receice receice=new Receice(socket);
receice.start();
//发消息
OutputStream outputStream = socket.getOutputStream();
while(true) {
System.out.println("发送:");
outputStream.write(scanner.next().getBytes());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Receice extends Thread{
Socket socket;
public Receice(Socket socket){ //构造
this.socket=socket;
}
@Override
public void run() {
while (true) {
try {
InputStream inputStream = socket.getInputStream();
byte[] b = new byte[1024];
int p = inputStream.read(b);
String s = new String(b, 0, p);
System.out.println("返回数据为:" + s);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
通讯数据包,要符合自定义协议:
a)管理报文(服务器端接收):
management-login-姓名XX
management-logout-姓名XX
management-onlineusers
b)消息报文:
message-发送人-接收人-聊天内容
DatagramSocket类 :此类表示用来发送和接收数据报包的套接字。
DatagramSocket(int port)
DatagramSocket(int port, InetAddress laddr)
void close()
关闭此数据报套接字。
void connect(InetAddress address, int port)
将套接字连接到此套接字的远程地址。
void disconnect()
断开套接字的连接。
boolean isClosed()
返回是否关闭了套接字。
boolean isConnected()
返回套接字的连接状态。
void receive(DatagramPacket p)
从此套接字接收数据报包。
void send(DatagramPacket p)
从此套接字发送数据报包。
·
DatagramPacket 类 此类表示数据报包。
byte[] getData()
返回数据缓冲区。
int getLength()
返回将要发送或接收到的数据的长度。
void setData(byte[] buf)
为此包设置数据缓冲区。
void setData(byte[] buf, int offset, int length)
为此包设置数据缓冲区。
void setLength(int length)
为此包设置长度。
基本的UDP通讯
public class UDPServer {
public static void main(String[] args) throws Exception {
Scanner scanner=new Scanner(System.in);
DatagramSocket datagramSocket=new DatagramSocket(18889);
while (true) {
//接
byte[] b = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(b, b.length);//构造一个 DatagramPacket用于接收length长度的数据包 。
datagramSocket.receive(datagramPacket);//从此套接字接收数据报包。
System.out.println("接收数据:");
System.out.println(new String(b, 0, datagramPacket.getLength()));//length,返回要发送的数据的长度或接收到的数据的长度。
//发
System.out.print("请输入:");
String s = scanner.next();
DatagramPacket datagramPacket1 = new DatagramPacket(s.getBytes(), s.length(), InetAddress.getByName("127.0.0.1"), 18890);//构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。
datagramSocket.send(datagramPacket1);//从此套接字发送数据报包
}
}
}
public class UDPkehu {
public static void main(String[] args) throws Exception {
Scanner scanner=new Scanner(System.in);
DatagramSocket datagramSocket=new DatagramSocket(18890);
while (true) {
//发
System.out.print("请输入:");
String s = scanner.next();
DatagramPacket datagramPacket1 = new DatagramPacket(s.getBytes(), s.length(), InetAddress.getByName("127.0.0.1"), 18889);//构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。
datagramSocket.send(datagramPacket1);//从此套接字发送数据报包
//接
byte[] b = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(b, b.length);//构造一个 DatagramPacket用于接收length长度的数据包 。
datagramSocket.receive(datagramPacket);//从此套接字接收数据报包。
System.out.println("返回数据:");
System.out.println(new String(b, 0, datagramPacket.getLength()));//返回要发送的数据的长度或接收到的数据的长度。
}
}
}