计算机网络是线代通信技术与计算机技术相结合的产物,计算机网络主要可以提供
通信协议一般由三部分组成:一是语义部分,用于决定双方对话类型;二是语法部分,用于决定双方对话的格式;三是变化规则,用于决定通信双方的应答关系。
应用层:与其它计算机进行通讯的一个应用,它是对应应用程序的通信服务的。有HTTP, FTP , NFS, SMTP, TELNET
表示层:这一层主要是定义数据格式及加密。如加密, ASCII
会话层:它定义了如何开始、控制和结束一个会话,包括对多个双向消息的控制和管理,以便在只完成连续消息的一部分时可以通知应用,从而使表示层看到的数据是连续的。如 RPC,SQL
传输层:这层的功能包括是否选择差错恢复协议还是无差错恢复协议,及在泳衣主机上对不同应用的数据流的输入进行复用,还包括对收到的顺序不对的数据包的重新排序功能,如 TCP UDP SPX
网络层:这层对端对端的包传输进行定义,它定义了能够标识所有结点的逻辑地址,还定义了路由实现的方式和学习的方式。如IP
数据链路层:它定义了在单个链路上如何传输数据。这些协议与被讨论的各种介质有关
物理层:OSI的物理层规范是有关传输介质的特性,这些规范通常也参考了其他组织制定的标准。
IP地址用于唯一标识网络中的一个通信实体,这个通信实体既可以是一个主机,也可以是路由器的某个端口,。而在基于IP协议的网络中传输数据包都必须使用IP地址来进行标识。
端口,程序与外界进行交互的出入口。
Tcp/IP通信协议是一种可靠的网络协议,他在通信的两端建立一个socket,从而形成虚拟的网络链路。一旦建立了虚拟网络链路,两端的程序就可以通过该链路进行通信。
IP 是Internet上使用的一个关键协议,通过IP协议,使internet成为一个允许连接不同类型的计算机和不同 *** 作系统的网络。同时还需要TCP协议来提供可靠且无差错的服务。
TCP协议被称为端对端协议,这是因为他在两台计算机的连接中起了非常重要的角色,当一台计算机需要与另外一台计算机连接时,TCP协议会让他们之间建立一个虚拟链路,用于发送和接受数据。
TCP协议负责收集这些数据包,并将其按照适当的顺序传送,接收端收到数据包后将其正确的还原。TCP保证数据包在传送过程中准确无误。TCP协议采用重发机制,当一个通信实体发送一个消息给另外一个通信实体后,需要接收到另外一个通信实体的确认信息,如果没有接收到该确认信息,则会重发信息。
使用socket之前,必须先创建socket对象,可通过该类的构造器来创建socket实例。
socket.socket(family = AF_INET, type= SOCK_STREAM, proto=0, fileno= None)
socket对象常用的方法:
基本步骤
创建客户端的步骤:
小实例:服务端
客户端:
通过这样就可以实现socket之间的通信。
package chat1import java.awt.*
import javax.swing.*
import java.awt.event.*
import java.net.*
import java.io.*
public class Client extends JFrame{
/**
*
*/
private static final long serialVersionUID = -4733717749265129757L
Container con=null
JTextArea jta = null
JTextField jtf = null
//ArrayList al = new ArrayList()
//ServerSocket ss = null
Socket s = null
Client(String ip,int port){
try{
s=new Socket(ip,port)//创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
launchFrame()
}
catch(Exception e){
e.printStackTrace()
}
new Thread(new ClientR()).start()
}
public void sent(String str){ //发送消息方法
try{
DataOutputStream dos = new DataOutputStream(s.getOutputStream())// 创建一个新的数据输出流,将数据写入指定 返回s的套接字的输出流。
dos.writeUTF(str)
}
catch(Exception e){
e.printStackTrace()
}
}
public void disconnect() throws Exception
{
s.close()//失去连接,关闭线程s
}
class ClientR implements Runnable{//客户端运行
/*Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run 的无参数方法。
设计该接口的目的是为希望在活动时执行代码的对象提供一个公共协议。例如,Thread 类实现了 Runnable。
激活的意思是说某个线程已启动并且尚未停止。
此外,Runnable 为非 Thread 子类的类提供了一种激活方式。
通过实例化某个 Thread 实例并将自身作为运行目标,就可以运行实现 Runnable 的类而无需创建 Thread 的子类。
大多数情况下,如果只想重写 run() 方法,而不重写其他 Thread 方法,那么应使用 Runnable 接口。这很重要,
因为除非程序员打算修改或增强类的基本行为,否则不应为该类创建子类。
*/
public void run(){
try{
DataInputStream dis = new DataInputStream(s.getInputStream())//使用指定的底层 s.getInputStream(s的套接字的输入流) 创建一个 DataInputStream(数据输入流)
String str = dis.readUTF()
while(true){
System.out.println (str)
jta.append(str+"\n")
str = dis.readUTF()
}
}
catch(Exception e){
e.printStackTrace()
}
}
}
public void startClient(){ //客户端启用
try{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in))//读取数据流
String str=br.readLine()
while(true){
sent(str)//发送数据
if(str.equals("q")){ //如果读取的字符为q
disconnect()//断开连接
return
}
str=br.readLine()
}
}
catch(Exception e){
e.printStackTrace()
}
}
public void launchFrame() throws IOException{ //客户端面板布局
con = this.getContentPane()
jta = new JTextArea()
jtf = new JTextField()
final JTextField jtf1=new JTextField(10)
final JButton jb=new JButton("确认")
Panel p=new Panel()
//Panel p1=new Panel()
JLabel jl=new JLabel()
jl.setText("your name:")
//jl.getVerticalTextPosition()
jtf1.setBackground(Color.PINK)
jtf1.setBounds(10, 10, 10, 10)
p.add(jl)
p.add(jtf1)
p.add(jb)
jb.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//e.getWhen()
e.getActionCommand()
jtf.setText(jtf1.getText().toString()+"say:")
}
})
jta.setBackground(Color.LIGHT_GRAY)
jta.setEditable(false)//不可编辑文本域
JScrollPane jsp = new JScrollPane(jta, //jta上滚动条的创建
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED)
//con.add(jb,BorderLayout.WEST)
con.add(jsp,BorderLayout.CENTER)
con.add(p,BorderLayout.NORTH)
con.add(jtf,BorderLayout.SOUTH)
jtf.addActionListener(new ActionListener(){ ///事件监听
public void actionPerformed(ActionEvent e){
String str = jtf.getText().toString()
Client.this.sent(str)
jtf.setText(jtf1.getText().toString()+"say:")
}
})
this.setTitle("聊天客户端,袭风版")
this.setBounds(200,200,300,400)
this.setDefaultCloseOperation(EXIT_ON_CLOSE)
this.setBackground(Color.blue)
this.setVisible(true)
}
public static void main (String[] args) {
Client cli = new Client("127.168.1.1",3456)//创建一个客户端,并将其连接到指定 IP 地址的指定端口号,其端口号与服务器端一致。与服务器建立连接
cli.startClient()//127.0.0.1为本机端口
}
}
package chat1
import java.net.*
import java.io.*
import java.util.*
//import java.awt.event.*
import javax.swing.*
import java.awt.*
public class Server extends JFrame{
/**
* 套接字接口可分为三类:公认端口 注册端口 动态和/或私有端口
套接字,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程
*/
private static final long serialVersionUID = 4130666237241201704L
Container con = null//容器
JTextArea jta = null//文本区
ServerSocket ss = null//初始化服务器套接字
ArrayList al = new ArrayList()//ArrayList容器
Server(int port){ //构造函数
try{
ss=new ServerSocket(port)// 创建绑定到特定端口的服务器套接字。
}
catch(Exception e){
e.printStackTrace()
}
launchFrame()
}
public void severStart(){ //线程开始
while(true){
try{
Socket s = ss.accept()//侦听并接受到此套接字(port)的连接。
al.add(new ServerR(s))
jta.append("New Client:"+"\n Ip: "+s.getInetAddress()+":"+s.getPort()+"\n" //得到客户端本地地址,端口和客户端数量
+"Clients count:"+al.size()+"\n")
}
catch(Exception e){
e.printStackTrace()
}
}
}
class ServerR implements Runnable{
Socket s = null//创建新服务线程
ServerR(Socket s){
this.s = s
new Thread(this).start()//启动新线程
}
public void sent(String str){ //发送数据流方法
try{
DataOutputStream dos = new DataOutputStream(s.getOutputStream())//从s套接字中读出输出数据流
dos.writeUTF(str)//使用 UTF-8 修改版编码将一个字符串写入基础输出流。
}
catch(Exception e){
e.printStackTrace()
}
}
public void run(){
try{
DataInputStream dis = new DataInputStream(s.getInputStream())
String str = dis.readUTF()//读出输入的数据流
while(true){
// System.out.println (str)
Iterator ite = al.iterator()//生成list迭代器
while(ite.hasNext()){ //如果仍有可迭代的元素,返回true
((ServerR)ite.next()).sent(str)//返回(ServerR)的下一个元素,并发送它
//先遍历ServerR中的所有线程
}
str=dis.readUTF()
}
}
catch(Exception e){
try{ //客户端关闭捕捉
s.close()//关闭一个相关客户端线程
al.remove(this)//从迭代器指向的集合中移除迭代器返回的最后一个元素
jta.append("A client quit!\nClients count:"+al.size()+"\n")//统计客户端现有的数量
}
catch(Exception e2){
e2.printStackTrace()
}
e.printStackTrace()
}
}
}
public void launchFrame(){ //服务器端面板布局
con = this.getContentPane()
jta = new JTextArea()
jta.setEditable(false)//不可编辑文本域
JScrollPane jsp = new JScrollPane(jta,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED)
con.add(jsp,BorderLayout.CENTER)
this.setTitle("聊天服务端,袭风版")
this.setBounds(200,200,300,400)
this.setDefaultCloseOperation(EXIT_ON_CLOSE)
this.setVisible(true)
}
public static void main (String[] args) {
Server s = new Server(3456)//创建服务器S 端口为3456
s.severStart()
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)