通信简单实现

本文介绍了一种基于Java的简易服务器与客户端通信实现方法,包括如何利用ServerSocket和Socket进行通信,以及如何通过输入输出流交换信息。同时,还探讨了如何搭建可视化的聊天界面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 通信的基础:(1)电脑间的通信是程序间的通信,我们电脑在运行时可能开有很多程序,而进行通信的可能只有几个程序,比如浏览器、QQ等。(2)每个电脑都有一个独立的IP地址,通过IP地址,可以找到这台电脑。(3)只有IP地址还不够,因为有那么多程序,仅靠这些还不知道是哪个程序要通信,所以还需要端口号,就像一台电脑有很多有编号的管道和外界相通,我们知道那个管道打开了,并且需要通信的程序就在管道另一端等待接入,就可以连接通信。
2.简单的服务器实现:服务器和客户端之间的通信是通过Socket(套接字)来实现,套接字是两台机器间通信的端点。首先服务器实例化一个服务器套接字,通过类ServerSocket类来实例化,然后接受客户端的套接字连接,实现彼此通信。而通过Socket来得到输入流(InputStream)来得到彼此的信息,和输出流(OutputStream)来发送给彼此信息。建立服务器后并且运行后可以通过cmd的telnet来连接到服务器,当然windows 7的保护措施不予许cmd使用telnet,你可以打开“控制面板”,找到程序和功能,然后点击左上方的“打开或关闭windows功能”,会弹出windows功能的对话框,这个对话框里面有许多windows的小功能,再找到Telent Client,打上勾,确认来获得使用的权限。
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
* 简单服务器的类
* @author 剑晨
*
*/
public class ServerTest {

/**
* @param args
*/
public static void main(String[] args) {//程序入口
new ServerTest().startServer();

}
public void startServer(){
try {
/*
* 传入端口号,实例化服务器对象,我们每台电脑大约六万多个端口,
* 有些端口是有固定被占用的,我们尽量选择大一些的端口号,并且
* 会抛出端口号不存在或则被占用的异常
*/
ServerSocket server=new ServerSocket(9090);
System.out.println("-----服务器创建成功-----");
/*
* 接下来,服务器进入等待客户端连接的状态,并且程序会卡在这里
* 无法继续执行后续代码,直到客户端链接进来
*/

Socket client=server.accept();
System.out.println("-----客户端链接成功-----");
//得到输出流,向客户端发送信息
OutputStream ous=client.getOutputStream();
//将信息转为byte数组传给客户端
String s="Hello!";
byte[] b=s.getBytes();
ous.write(b);
//刷新此输出流并强制写出所有缓冲的输出字节
ous.flush();
//关闭输出流
ous.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}

[img]http://dl2.iteye.com/upload/attachment/0087/0352/600c1825-fb15-3d7e-8d27-1ea44cbc8882.png[/img]

按下回车键后
[img]http://dl2.iteye.com/upload/attachment/0087/0350/29c97895-b71d-3b61-874e-ecc7c4ff3a05.png[/img]

3.我们发现这样服务器只发出一句话后客户端就会出现遗失对主机的连接的字样,这说明连接已断开,因为服务器代码已执行结束,程序已结束。你可以通过循环获得服务器也就是把accept写在循环里,不停得到客户端。当然你也可以把输入输出流单独拿出去写在线程里不停输入输出以实现对话。我想这些应该很容易实现。
4.把客户端单独拿出来,也就是不在使用cmd的telnet而是使用自己编写的程序。其使用的是Socket传入服务器IP地址和端口号已连接服务器。
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
/**
* 简单客户端类
* @author 陈建
*
*/
public class ChatClient {
private String serverIP;//服务器IP地址
private int serverPort;//服务器端口号
OutputStream ous;//输出流
/**
* 构造器
* @param serverIP:服务器IP地址
* @param serverPort:服务器端口号
*/
public ChatClient(String serverIP,int serverPort){
this.serverIP=serverIP;
this.serverPort=serverPort;
}
public void startClient(){
try {
//实例化客户端Socket,传入String型服务器IP地址,和int型端口号
Socket client=new Socket(serverIP,serverPort);
//得到输出流,以发送给服务器信息
ous=client.getOutputStream();
//得到输入流,以读取服务器信息
InputStream ins=client.getInputStream();
//将输入流包装为BufferedReader并启动输入流的线程
BufferedReader buffReader=new BufferedReader(new InputStreamReader(ins));
new InputThread(buffReader).start();
} catch (Exception e) {
e.printStackTrace();
}

}
}

import java.io.BufferedReader;
import java.io.IOException;

/**
* 客户端输入流线程
* @author 剑晨
*
*/
public class InputThread extends Thread{
private BufferedReader buffReader;
private int count=1;//计数器
/**
* 构造器
* @param buffReader
*/
public InputThread(BufferedReader buffReader){
this.buffReader=buffReader;
}
/**
* 重写的run方法,以循环读入数据
*/
public void run(){
while(true){
try {
String s=buffReader.readLine();//读入字符串
ChatFrame.leftg.drawString("客户端:"+s, 10, count*20);
count++;
} catch (IOException e) {
e.printStackTrace();
}
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
/**
* 聊天界面监听器
* @author 剑晨
*
*/
public class chatListener implements ActionListener{

private ChatClient client;//客户端对象
private ChatFrame frame;//聊天界面对象
private int count=1;//计数器
/**
* 构造器
* @param frame:聊天界面对象
* @param client:客户端对象
*/
public chatListener(ChatFrame frame,ChatClient client){
this.frame=frame;
this.client=client;
}
public void actionPerformed(ActionEvent e) {
String command=e.getActionCommand();
if("Send".equals(command)){
String s=frame.textField.getText();
//因为BufferedReader读取需要以回车键结尾的句子,所以在每个句子后加入“\r”
s = s + "\r";
byte[] b=s.getBytes();
try {
client.ous.write(b);//发送文本框的内容
} catch (IOException e1) {
e1.printStackTrace();
}
frame.rightg.drawString("服务器:"+s, 10, 20*count);//并在右侧JPanel画出文本框内容
count++;
}

}

}

做到服务器和客户端的可视化,启动服务器后
[img]http://dl2.iteye.com/upload/attachment/0087/0372/b732e6ef-13fc-3525-9e1e-37456d774197.png[/img]
客户端
[img]http://dl2.iteye.com/upload/attachment/0087/0374/fd1c6d11-89d5-38f1-946d-d3c484183c48.png[/img]
链接后
[img]http://dl2.iteye.com/upload/attachment/0087/0376/80a214bc-3ebb-3eb2-b82f-908f732f8248.png[/img]
[img]http://dl2.iteye.com/upload/attachment/0087/0378/e046ae2b-a0e6-313d-ad49-ed187a3bad75.png[/img]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值