基于java TCP网络通信的实例详解
程序员文章站
2023-12-13 20:49:10
java中设计网络编程模式的主要有tcp和udp两种,tcp是属于即时通信,udp是通过数据包来进行通信,udp当中就会牵扯到数据的解析和传送。在安全性能方面,tcp要略胜...
java中设计网络编程模式的主要有tcp和udp两种,tcp是属于即时通信,udp是通过数据包来进行通信,udp当中就会牵扯到数据的解析和传送。在安全性能方面,tcp要略胜一筹,通信过程中不容易出现数据丢失的现象,有一方中断,两方的通信就会结束,udp数据包传送的过程当中,一方中断,数据包有很大的可能丢失,还有可能传来的数据包的顺序是错乱的;在效率方面,udp要比tcp快的不只是一点点的问题,若终端有解析数据方法的函数,数据包就会源源不断的传送过来,然后反馈回去。
以上都是我自己的理解,下面是关于tcp协议通信的两个类;
server类:
package tcp;
import java.io.*;
import java.net.*;
import javax.swing.*;
public class server {
//服务器端的输入流
static bufferedreader br;
//服务器端的输出流
static printstream ps;
//服务器相关的界面组件
static jtextarea text;
jframe frame;
public server(){
//服务器端的界面的实例化
jframe frame=new jframe("服务器端");
text=new jtextarea();
jscrollpane scroll =new jscrollpane(text);
frame.add(scroll);
frame.setvisible(true);
frame.setsize(300,400);
//这里设置服务器端的文本框是不可编辑的
text.seteditable(false);
}
public static void main(string[] args) throws exception{
new server(); //生成服务器界面
//通过服务器端构造函数 serversocket(port) 实例化一个服务器端口
serversocket server=new serversocket(2000);
text.append("监听2000端口"+"\n");
//实例化一个接受服务器数据的对象
socket client=server.accept();
br =new bufferedreader(new inputstreamreader(client.getinputstream()));
ps =new printstream(client.getoutputstream());
string msg;
//如果输入流不为空,将接受到的信息打印到相应的文本框中并反馈回收到的信息
while ((msg =br.readline())!=null)
{
text.append("服务器端收到:"+msg+"\n");
ps.println(msg);
if(msg.equals("quit"))
{
text.append("客户端“2000”已退出!"+"\n");
text.append("服务器程序将退出!");
break;
}
}
ps.close();
br.close();
client.close();
}
}
client类:
package tcp;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import java.net.*;
public class client implements actionlistener{
//这里有两个图形界面,一个是连接的frame,另一个和服务器通信的界面frame1
private jframe frame;
private jlabel adress;
private jlabel port;
jtextfield adresstext;
jtextfield porttext;
jbutton connect;
private jframe frame1;
private jlabel shuru;
private jpanel panel1;
private jpanel panel2;
private jlabel jieshou;
jbutton send;
static jtextarea shurukuang;
static textarea jieshoukuang;
//从服务端接受的数据流
static bufferedreader br1;
//从客户端输出的数据流
static printstream ps;
//从通信界面中的输入框接受的数据流
static bufferedreader br2;
static socket client;
//将输入框字符串转换为字符串流所需的字符串的输入流
static bytearrayinputstream stringinputstream ;
public client() {
//连接界面的实例化
frame=new jframe();
adress=new jlabel("ip 地址");
port =new jlabel("端口号");
adresstext=new jtextfield("127.0.0.1",10);
porttext=new jtextfield("2000",10);
connect=new jbutton("连接");
//连接界面的布局
frame.setlayout(new flowlayout());
frame.add(adress);
frame.add(adresstext);
frame.add(port);
frame.add(porttext);
frame.add(connect);
frame.setvisible(true);
frame.setsize(200,150);
connect.addactionlistener(this);
//通信界面的实例化
frame1=new jframe();
shuru=new jlabel("请输入");
shurukuang=new jtextarea("请输入····",5,40);
panel1=new jpanel();
panel1.add(shuru);
panel1.add(shurukuang);
panel1.setlayout(new flowlayout());
send=new jbutton("发送");
panel2=new jpanel();
jieshou=new jlabel("已接受");
jieshoukuang=new textarea(8,60);
jieshoukuang.seteditable(false);
panel2.add(jieshou);
panel2.add(jieshoukuang);
panel2.setlayout(new flowlayout());
frame1.setlayout(new flowlayout());
//通信界面都的布局
frame1.add(borderlayout.north,panel1);
frame1.add(send);
frame1.add(borderlayout.south,panel2);
//连接时通信界面是处于看不到的
frame1.setvisible(false);
frame1.setsize(500,350);
send.addactionlistener(this);
}
//两个界面当中都有相应的按钮时间,为相应的时间添加动作
public void actionperformed(actionevent e) {
if(e.getsource()==connect){
try {
//当触发连接按钮时,实例化一个客户端
client=new socket("127.0.0.1",2000);
//隐藏连接界面,显示通信界面
frame.setvisible(false);
frame1.setvisible(true);
jieshoukuang.append("已经连接上服务器!"+"\n");
} catch (ioexception e1){
system.out.println("链接失败!");
e1.printstacktrace();
}
}
//通信界面中的发送按钮相应的时间处理
if(e.getsource()==send){
//将输入框中的字符串转换为字符串流
stringinputstream = new bytearrayinputstream((shurukuang.gettext()).getbytes());
br2 =new bufferedreader(new inputstreamreader(stringinputstream));
string msg;
try{
while((msg=br2.readline())!=null){
ps.println(msg); //将输入框中的内容发送给服务器端
jieshoukuang.append("向服务器发送:"+msg+"\n");
jieshoukuang.append("客户端接受相应:"+br1.readline()+"\n");
if(msg.equals("quit"))
{
jieshoukuang.append("客户端将退出!");
br1.close();
ps.close();
client.close();
frame1.setvisible(false);
break;
}
}
}catch(ioexception e2){
system.out.println("读输入框数据出错!");
}
shurukuang.settext("");
}
}
public static void main(string[] args) throws ioexception{
new client(); //实例化连接界面
client=new socket("127.0.0.1",2000);
//从服务端接受的数据
br1=new bufferedreader(new inputstreamreader(client.getinputstream()));
//从客户端输出的数据
ps =new printstream(client.getoutputstream());
}
}
写完这两个类以后还是有几个问题:
1)main 函数为什么非要用 static 来修饰?
2)缓冲对象 bufferedreader 为什么不能直接用于判断,非要将读到的数据赋值给字符串来进行操作?
3)在连接界面当中的 connect 按钮事件 当中我有实例化一个 客户端的对象,但是我注释掉主函数当中 client=new socket("127.0.0.1",2000); 的这一句的时候,就会发现抛出 nullpointexception 异常,我很不理解?
希望有看到这文章的大牛们能不吝赐教,我也正在不停的翻着《think in java》希望在某个不起眼的角落里面发现我的答案。
以上都是我自己的理解,下面是关于tcp协议通信的两个类;
server类:
复制代码 代码如下:
package tcp;
import java.io.*;
import java.net.*;
import javax.swing.*;
public class server {
//服务器端的输入流
static bufferedreader br;
//服务器端的输出流
static printstream ps;
//服务器相关的界面组件
static jtextarea text;
jframe frame;
public server(){
//服务器端的界面的实例化
jframe frame=new jframe("服务器端");
text=new jtextarea();
jscrollpane scroll =new jscrollpane(text);
frame.add(scroll);
frame.setvisible(true);
frame.setsize(300,400);
//这里设置服务器端的文本框是不可编辑的
text.seteditable(false);
}
public static void main(string[] args) throws exception{
new server(); //生成服务器界面
//通过服务器端构造函数 serversocket(port) 实例化一个服务器端口
serversocket server=new serversocket(2000);
text.append("监听2000端口"+"\n");
//实例化一个接受服务器数据的对象
socket client=server.accept();
br =new bufferedreader(new inputstreamreader(client.getinputstream()));
ps =new printstream(client.getoutputstream());
string msg;
//如果输入流不为空,将接受到的信息打印到相应的文本框中并反馈回收到的信息
while ((msg =br.readline())!=null)
{
text.append("服务器端收到:"+msg+"\n");
ps.println(msg);
if(msg.equals("quit"))
{
text.append("客户端“2000”已退出!"+"\n");
text.append("服务器程序将退出!");
break;
}
}
ps.close();
br.close();
client.close();
}
}
client类:
复制代码 代码如下:
package tcp;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import java.net.*;
public class client implements actionlistener{
//这里有两个图形界面,一个是连接的frame,另一个和服务器通信的界面frame1
private jframe frame;
private jlabel adress;
private jlabel port;
jtextfield adresstext;
jtextfield porttext;
jbutton connect;
private jframe frame1;
private jlabel shuru;
private jpanel panel1;
private jpanel panel2;
private jlabel jieshou;
jbutton send;
static jtextarea shurukuang;
static textarea jieshoukuang;
//从服务端接受的数据流
static bufferedreader br1;
//从客户端输出的数据流
static printstream ps;
//从通信界面中的输入框接受的数据流
static bufferedreader br2;
static socket client;
//将输入框字符串转换为字符串流所需的字符串的输入流
static bytearrayinputstream stringinputstream ;
public client() {
//连接界面的实例化
frame=new jframe();
adress=new jlabel("ip 地址");
port =new jlabel("端口号");
adresstext=new jtextfield("127.0.0.1",10);
porttext=new jtextfield("2000",10);
connect=new jbutton("连接");
//连接界面的布局
frame.setlayout(new flowlayout());
frame.add(adress);
frame.add(adresstext);
frame.add(port);
frame.add(porttext);
frame.add(connect);
frame.setvisible(true);
frame.setsize(200,150);
connect.addactionlistener(this);
//通信界面的实例化
frame1=new jframe();
shuru=new jlabel("请输入");
shurukuang=new jtextarea("请输入····",5,40);
panel1=new jpanel();
panel1.add(shuru);
panel1.add(shurukuang);
panel1.setlayout(new flowlayout());
send=new jbutton("发送");
panel2=new jpanel();
jieshou=new jlabel("已接受");
jieshoukuang=new textarea(8,60);
jieshoukuang.seteditable(false);
panel2.add(jieshou);
panel2.add(jieshoukuang);
panel2.setlayout(new flowlayout());
frame1.setlayout(new flowlayout());
//通信界面都的布局
frame1.add(borderlayout.north,panel1);
frame1.add(send);
frame1.add(borderlayout.south,panel2);
//连接时通信界面是处于看不到的
frame1.setvisible(false);
frame1.setsize(500,350);
send.addactionlistener(this);
}
//两个界面当中都有相应的按钮时间,为相应的时间添加动作
public void actionperformed(actionevent e) {
if(e.getsource()==connect){
try {
//当触发连接按钮时,实例化一个客户端
client=new socket("127.0.0.1",2000);
//隐藏连接界面,显示通信界面
frame.setvisible(false);
frame1.setvisible(true);
jieshoukuang.append("已经连接上服务器!"+"\n");
} catch (ioexception e1){
system.out.println("链接失败!");
e1.printstacktrace();
}
}
//通信界面中的发送按钮相应的时间处理
if(e.getsource()==send){
//将输入框中的字符串转换为字符串流
stringinputstream = new bytearrayinputstream((shurukuang.gettext()).getbytes());
br2 =new bufferedreader(new inputstreamreader(stringinputstream));
string msg;
try{
while((msg=br2.readline())!=null){
ps.println(msg); //将输入框中的内容发送给服务器端
jieshoukuang.append("向服务器发送:"+msg+"\n");
jieshoukuang.append("客户端接受相应:"+br1.readline()+"\n");
if(msg.equals("quit"))
{
jieshoukuang.append("客户端将退出!");
br1.close();
ps.close();
client.close();
frame1.setvisible(false);
break;
}
}
}catch(ioexception e2){
system.out.println("读输入框数据出错!");
}
shurukuang.settext("");
}
}
public static void main(string[] args) throws ioexception{
new client(); //实例化连接界面
client=new socket("127.0.0.1",2000);
//从服务端接受的数据
br1=new bufferedreader(new inputstreamreader(client.getinputstream()));
//从客户端输出的数据
ps =new printstream(client.getoutputstream());
}
}
写完这两个类以后还是有几个问题:
1)main 函数为什么非要用 static 来修饰?
2)缓冲对象 bufferedreader 为什么不能直接用于判断,非要将读到的数据赋值给字符串来进行操作?
3)在连接界面当中的 connect 按钮事件 当中我有实例化一个 客户端的对象,但是我注释掉主函数当中 client=new socket("127.0.0.1",2000); 的这一句的时候,就会发现抛出 nullpointexception 异常,我很不理解?
希望有看到这文章的大牛们能不吝赐教,我也正在不停的翻着《think in java》希望在某个不起眼的角落里面发现我的答案。