导航:首页 > 编程知识 > 如何理解socket编程端口

如何理解socket编程端口

发布时间:2023-08-15 17:59:36

java Socket初步详解

网络编程的基本模型就是客户机到服务器模型 简单的说就是两个进程之间相互通讯 然后其中一个必须提供一个固定的位置 而另一个则只需要知道这个固定的位置 并去建立两者之间的联系 然后完成数据的通讯就可以了 这里提供亩悉猜固定位置的通常称为服务器 而建立联系的通常叫做客户端 基于这个简单的模型 就可以进入网络编程啦

Java对这个模型的支持有很多种Api 而这里我只想介绍有关Socket的编程接口 对于Java而言已经简化了Socket的编程接口 首先我们来讨论有关提供固定位置的服务方是如何建立的 Java提供了ServerSocket来对其进行支持 事实上当你创建该类的一个实力对象并提供一个端口资源你就建立了一个固定位置可以让其他计算机来访问你 ServerSocket server=new ServerSocket( );这里稍微要注意的是端口的分配必须是唯一的 因为端口是为了唯一标识每台计算机唯一服务的 另外端口号是从 ~ 之间的 前 个端口已经被Tcp/Ip 作为保留端口 因此你所分配的端口只能是 个之后的 好了 我们有了固定位置 现在所需要的就是一根连接线了 该连接线由客户方首先提出要求 因此Java同样提供了一个Socket对象来对其进行支持 只要客户方创建一个Socket的实例对象进行支持就可以了 Socket client

=new Socket(InetAddress getLocalHost() );客户机必须知道有关服务器的IP地址 对于著一点Java也提供了一个相关的类InetAddress 该对象的实例必须通过它的静态方法来提供 它的静态方法主要提供了得到本机IP 和通过名字或IP直接得到InetAddress的方法

上面的方法基本可以建立一条连线让两台计算机相互交流了 可是数据是如何传输的呢?事实上I/O操作总是和网络编程息息相关的 因为底层的网络是继续数据的 除非远程调用 处理问题的核心在执行上 否则数据的陆帆交互还是依赖于IO操作的 所以你也必须导入java io这个包 java的IO操作也不复杂 它提供了针对于字节流和Unicode的读者和写者 然后也提供了一个缓冲用于数据的读写

BufferedReader in=new BufferedReader(new InputStreamReader(server getInputStream()));

PrintWriter out=new PrintWriter(server getOutputStream());

上面两句就是建立缓冲并把原始的字节流转变为Unicode可以操作 而原始的字节流来源于Socket的两个方法 getInputStream()和getOutputStream()方 分别用来得到输入和输出 那么现在有了基本的模型和基本的操作工具 我们可以做一个简单的Socket例程了

服务方:

import java io *;

import *;

public class MyServer {

public static void main(String[] args) throws IOException{

ServerSocket server=new ServerSocket( );

Socket client=server accept();

BufferedReader in=new BufferedReader(new InputStreamReader(client getInputStream()));

迅型PrintWriter out=new PrintWriter(client getOutputStream());

while(true){

String str=in readLine();

System out println(str);

out println( has receive );

out flush();

if(str equals( end ))

break;

}

client close();

}

}

这个程序的主要目的在于服务器不断接收客户机所写入的信息只到 客户机发送 End 字符串就退出程序 并且服务器也会做出 Receive 为回应 告知客户机已接收到消息

客户机代码:

import *;

import java io *;

public class Client{

static Socket server;

public static void main(String[] args)throws Exception{

server=new Socket(InetAddress getLocalHost() );

BufferedReader in=new BufferedReader(new InputStreamReader(server getInputStream()));

PrintWriter out=new PrintWriter(server getOutputStream());

BufferedReader wt=new BufferedReader(new InputStreamReader(System in));

while(true){

String str=wt readLine();

out println(str);

out flush();

if(str equals( end )){

break;

}

System out println(in readLine());

}

server close();

}

}

客户机代码则是接受客户键盘输入 并把该信息输出 然后输出 End 用来做退出标识

这个程序只是简单的两台计算机之间的通讯 如果是多个客户同时访问一个服务器呢?你可以试着再运行一个客户端 结果是会抛出异常的 那么多个客户端如何实现呢?

其实 简单的分析一下 就可以看出客户和服务通讯的主要通道就是Socket本身 而服务器通过accept方法就是同意和客户建立通讯 这样当客户建立Socket的同时 服务器也会使用这一根连线来先后通讯 那么既然如此只要我们存在多条连线就可以了 那么我们的程序可以变为如下:

服务器:

import java io *;

import *;

public class MyServer {

public static void main(String[] args) throws IOException{

ServerSocket server=new ServerSocket( );

while(true){

Socket client=server accept();

BufferedReader in=new BufferedReader(new InputStreamReader(client getInputStream()));

PrintWriter out=new PrintWriter(client getOutputStream());

while(true){

String str=in readLine();

System out println(str);

out println( has receive );

out flush();

if(str equals( end ))

break;

}

client close();

}

}

}

这里仅仅只是加了一个外层的While循环 这个循环的目的就是当一个客户进来就为它分配一个Socket直到这个客户完成一次和服务器的交互 这里也就是接受到客户的 End 消息 那么现在就实现了多客户之间的交互了 但是 问题又来了 这样做虽然解决了多客户 可是是排队执行的 也就是说当一个客户和服务器完成一次通讯之后下一个客户才可以进来和服务器交互 无法做到同时服务 那么要如何才能同时达到既能相互之间交流又能同时交流呢?很显然这是一个并行执行的问题了 所以线程是最好的解决方案

那么下面的问题是如何使用线程 首先要做的事情是创建线程并使得其可以和网络连线取得联系 然后由线程来执行刚才的操作 要创建线程要么直接继承Thread要么实现Runnable接口 要建立和Socket的联系只要传递引用就可以了 而要执行线程就必须重写run方法 而run方法所做的事情就是刚才单线程版本main所做的事情 因此我们的程序变成了这样:

import *;

import java io *;

public class MultiUser extends Thread{

private Socket client;

public MultiUser(Socket c){

this client=c;

}

public void run(){

try{

BufferedReader in=new BufferedReader(new InputStreamReader(client getInputStream()));

PrintWriter out=new PrintWriter(client getOutputStream());

//Mutil User but can t parallel

while(true){

String str=in readLine();

System out println(str);

out println( has receive );

out flush();

if(str equals( end ))

break;

}

client close();

}catch(IOException ex){

}finally{

}

}

public static void main(String[] args)throws IOException{

ServerSocket server=new ServerSocket( );

while(true){

//transfer location change Single User or Multi User

MultiUser mu=new MultiUser(server accept());

mu start();

}

}

}

lishixin/Article/program/Java/hx/201311/27013

㈡ 到底什么是Socket

本系列文章前面那些主要讲解的是计算机网络的理论基础,但对于即时通讯IM这方面的应用层开发者来说,跟计算机网络打道的其实是各种API接口。

本篇文章就来聊一下网络应用程序员最熟悉的Socket这个东西,抛开生涩的计算机网络理论,从应用层的角度来理解到底什纯喊么是Socket。

对于 Socket 的认识,本文将从以下几个方面着手介绍:

1) Socket 是什么;

2) Socket 是如何创建的;

3) Socket 是如何连接的;

4) Socket 是如何收发数据的;

5) Socket 是如何断开连接的;

6) Socket 套接字的删除等。

特别说明: 本文中提到的“Socket”、“网络套接字”、“套接字”,如无特殊指明,指的都是同一个东西哦。

Socket 是什么

一个数据包经由应用程序产生,进入到协议栈中进行各种报文头的包装,然后操作系统调用网卡驱动程序指挥硬件,把数据发送到对端主机。

我们大家知道,协议栈其实是位于操作系统中的一些协议的堆叠,这些协议包括 TCP、UDP、ARP、ICMP、IP等。即时通讯开发可以找蔚可云开发。

通常某个协议的设计都是为了解决特定问题的,比如:

1) TCP 的设计就负责安全可靠的传激盯输数据;

2) UDP 设计就是报文小,传输效率高;

3) ARP 的设计是能够通过 IP 地址查询物理(Mac)地址;

4) ICMP 的设计目的是返回错误报文给主机;

5) IP 设计的目的是为了实现大规模主机的互联互通。

应用程序比如浏览器、电子邮件、文件传输服务器等产生的数据,会通过传输层协议进行传输。而应用程序是不会和传输层直接建立联系的,而是有一个能够连接应用层和传输层之间的套件,这个套件就是 Socket 。

应用程序的下面: 就是操作系统内部,操作系统内部包括协议栈,协议栈是一系列协议的堆叠。

操作系统下面: 就是网卡驱动程序,网卡驱动程序负责控制网卡硬件,驱动程序驱动网卡硬件完成收发工作。

在操作系统内部有一块用于存放控制信息的存储空明裤和间,这块存储空间记录了用于控制通信的控制信息。其实这些控制信息就是 Socket 的实体,或者说存放控制信息的内存空间就是Socket的实体。

这里大家有可能不太清楚所以然,所以我用了一下 netstat 命令来给大伙看一下Socket是啥玩意。

Socket 是如何创建的

通过上节的讲解,现在你可能对 Socket 有了一个基本的认识,先喝口水,休息一下,让我们继续探究 Socket。

现在我有个问题, Socket 是如何创建的呢?

Socket 是和应用程序一起创建的。

应用程序中有一个 socket 组件,在应用程序启动时,会调用 socket 申请创建Socket,协议栈会根据应用程序的申请创建Socket:首先分配一个Socket所需的内存空间,这一步相当于是为控制信息准备一个容器,但只有容器并没有实际作用,所以你还需要向容器中放入控制信息;如果你不申请创建Socket所需要的内存空间,你创建的控制信息也没有地方存放,所以分配内存空间,放入控制信息缺一不可。至此Socket的创建就已经完成了。

Socket创建完成后,会返回一个Socket描述符给应用程序,这个描述符相当于是区分不同Socket的号码牌。根据这个描述符,应用程序在委托协议栈收发数据时就需要提供这个描述符。

Socket 是如何连接的

Socket创建完成后,最终还是为数据收发服务的。但是,在数据收发之前,还需要进行一步“连接”(术语就是 connect),建立连接有一整套过程。

实际上这个“连接”是应用程序通过 TCP/IP 协议标准从一个主机通过网络介质传输到另一个主机的过程。

Socket刚刚创建完成后,还没有数据,也不知道通信对象。

在这种状态下: 即使你让客户端应用程序委托协议栈发送数据,它也不知道发送到哪里。所以浏览器需要根据网址来查询服务器的 IP 地址,查询到目标主机后,再把目标主机的 IP 告诉协议栈。至此,客户端这边就准备好了。

在服务器上: 与客户端一样也需要创建Socket,但是同样的它也不知道通信对象是谁,所以我们需要让客户端向服务器告知客户端的必要信息: IP 地址和端口号 。

现在通信双方建立连接的必要信息已经具备,可以开始“连接”过程了。

首先: 客户端应用程序需要调用 Socket 库中的connect方法,提供 socket 描述符和服务器 IP 地址、端口号。

以下是connect的伪码调用:

1connect(<描述符>、<服务器IP地址和端口号>)

这些信息会传递给协议栈中的 TCP 模块,TCP 模块会对请求报文进行封装,再传递给 IP 模块,进行 IP 报文头的封装,然后传递给物理层,进行帧头封装。

之后通过网络介质传递给服务器,服务器上会对帧头、IP 模块、TCP 模块的报文头进行解析,从而找到对应的Socket。

Socket收到请求后,会写入相应的信息,并且把状态改为正在连接。

请求过程完成后: 服务器的 TCP 模块会返回响应,这个过程和客户端是一样的

Socket 是如何收发数据的

当控制流程上节中的连接过程回到应用程序之后,接下来就会直接进入数据收发阶段。

数据收发操作是从应用程序调用 write 将要发送的数据交给协议栈开始的,协议栈收到数据之后执行发送操作。

协议栈不会关心应用程序传输过来的是什么数据,因为这些数据最终都会转换为二进制序列,协议栈在收到数据之后并不会马上把数据发送出去,而是会将数据放在发送缓冲区,再等待应用程序发送下一条数据。

为什么收到数据包不会直接发送出去,而是放在缓冲区中呢?

因为只要一旦收到数据就会发送,就有可能发送大量的小数据包,导致网络效率下降(所以协议栈需要将数据积攒到一定数量才能将其发送出去)。

至于协议栈会向缓冲区放多少数据,这个不同版本和种类的操作系统有不同的说法。

㈢ Socket详解

1、 Socket(套接字)概念

网络上两个程序通过一个双向的通信连接实现数据的交换,这个连接的一段称为一个 socket ,socket是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进袜橡程的协议端口,远地主机的IP地址,远地进程的协议端口。

Socket是对TCP/IP协议的封装,它把复杂的TCP/IP协议族隐藏在Socket接口后面,提供一个易用的接口,所以Socket本身并不是协议,而是一个调用接口(API)。

在一定程度可以认为Socket位于应用层和传输层之间。创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。

2、 建立Socket连接

建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket,另一个运行于服务器端,称为ServerSocket。

套接字之间的连接过程分为 三个步骤 :

(1)服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。

(2)客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

(3)连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户 端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

3、 Socket连接与HTTP连接

由于通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用 中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。

而HTTP连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。

4、 关于Socket长连接的心跳包

心跳包就是为了避免一个连接长时间不活跃被关闭而定时发送的一个”骚扰”数据包。

Socket本身就是长连接的,那么为什么还要心跳包呢?

理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持粗好老长连接,保活。在获知了断线之后,服务器逻辑可能需要做一些事情,比如断线后的数据清理,重新连接……当然,这个自然是要由逻辑层根据需求去做了。总的来说,心跳包主要也就是用于长连接的保活和断线处理。一般的应用下,判定时间在30-40秒比较不错。如果实在要求高,那就在6-9秒。

如果不主动关闭socket的话,系统不会自动关闭的,除非当前进程挂掉了,操作系统把占用的socket回收了才会关闭。为什么需要心跳连接?主要是为了判断当前连接是否是有效的、可被使用的。在实际应用中假设一段时间没有数据传输时候理论上说应该连接是没有问题的,但是网络复杂,中途出现问题也是常见的,网线被掐断了、对方进程挂掉了、频繁丢包等,这时候TCP连接是不可使用的,但是对于应用层并不知道,如果需知道网络情况则要很复杂的超时进行了解,TCP从底层就实现了这样的功能。心跳机制是TCP在一段时间间隔后发送确认连接端是否还存在,如果存在的话就会回传一个包确定网络有效,如果岩升心跳包有问题,则通知上层应用当前网络有问题了。

这取决于你的server端的超时配置, 每个socket连接都是长连接,它是一个相当占用系统资源的通信管道, 如果这个长连接什么事也没干硬是要占着资源,则server端可以选择关闭这个连接,以省下资源让更多的用户连接进来。

所以,即便客户端的是采用死循环while(true)方式连到服务端,对于特定的客户端和服务端类型来说也需要一定时间间隔的心跳(告诉服务端,我还活着,虽然我没干活也没说话,但别把我关了)

阅读全文

与如何理解socket编程端口相关的资料

热点内容
90版本升级不送 浏览:186
工具箱英文 浏览:382
南翔嘉定编程课哪里好 浏览:853
win10改变文件格式 浏览:475
linux中的物理地址和虚拟地址 浏览:493
有哪些app可以接游戏订单 浏览:472
苹果硬盘数据恢复要多少钱 浏览:394
js绑定下拉框数据库数据 浏览:448
cad文件怎么复制到另一个文件里边 浏览:858
dxp钻孔文件 浏览:631
iphone大悦城换机 浏览:538
找结婚对象上什么网站 浏览:974
学生信息管理系统程序设计报告 浏览:640
微信文件怎么删除怎么恢复 浏览:407
编程程序怎么复制 浏览:467
文件更改 浏览:327
冰点文件路径 浏览:730
软件一点开文件就关闭 浏览:88
网络如何把人捧红 浏览:961
软件传输文件 浏览:184

友情链接