Socket【套接字】是什么,对于这个问题,初次接触的开发人员一般以为他只是一个通讯工具。

Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发 TCP/IP网络上的应用程序。

Socket 接口是访问 Internet 使用得最广泛的方法。
如果你有一台刚配好TCP/IP协议的主机,其IP地址是202.120.127.201, 此时在另一台主机或同一台主机上执行ftp 202.120.127.201,显然无法建立连接。因"202.120.127.201" 这台主机没有运行FTP服务软件。同样, 在另一台或同一台主机上运行浏览软件 如Netscape,输入"http://202.120.127.201",也无法建立连接。现在,如果在这台主机上运行一个FTP服务软件(该软件将打开一个Socket, 并将其绑定到21端口),再在这台主机上运行一个Web 服务软件(该软件将打开另一个Socket,并将其绑定到80端口)。这样,在另一台主机或同一台主机上执行ftp 202.120.127.201,FTP客户软件将通过21端口来呼叫主机上由FTP 服务软件提供的Socket,与其建立连接并对话。而在netscape中输入"http://202.120.127.201"时,将通过80端口来呼叫主机上由Web服务软件提供的Socket,与其建 立连接并对话。

在Internet上有很多这样的主机,这些主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原意那样,象一个多孔插座。以至于Socket为什么会被翻译成【套接字】,这只能说一个不懂技术的翻译大白话。

Socket开发其实很简单

用一个java应用程序模拟一个服务器端:

package mySocketServer;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set; import org.apache.commons.httpclient.HttpException; public class StubSocketServer { public static void main(String args[]) throws ParseException { StubSocketServer manager = new StubSocketServer();
manager.doListen();
} public void doListen() {
ServerSocket server = null;
try {
server = new ServerSocket(4700);
while (true) {
Socket client = server.accept();
new Thread(new SSocket(client)).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} /**
* <p>
* Title: 服务器进程
* </p>
*/
class SSocket implements Runnable { Socket client; public SSocket(Socket client) {
this.client = client;
} public void run() {
DataInputStream input;
DataOutputStream output;
try {
input = new DataInputStream(client.getInputStream());// 接收对象
output = new DataOutputStream(client.getOutputStream());// 回执对象 byte[] b = new byte[1024];
int msg = input.read(b);// 接收报文
System.out.println("msg===\n" + new String(b, 0, msg, "UTF-8"));
new Thread().sleep(5000);// 暂停1分钟60000 if (msg > 0) {
output.write("0012600112345600".getBytes("UTF-8"));
output.flush();
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("读取报文没有成功----");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

然后再做一个模拟的客户端,填上你的主机IP和监听的端口号就可以运行了:

            Charset charset = Charset.forName("UTF-8");
String src="send content";
byte[] bytes = src.getBytes(charset);
Socket socket = new Socket(serverIP, serverPort);
byte[] ret = new byte[20];
try {
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream(); os.write(bytes);
os.flush();
is.read(ret);
} finally {
socket.close();
}

还有一种读写方法就是

writeUTF(str);

str = readUTF();

直接发送和接收字符串,不建议使用

以下是某位大神的原理阐述,Server-Client模型程序的开发原理:

服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。

客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。

 
Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序。要学
Internet上的TCP/IP网络编程,必须理解Socket接口。
Socket接口设计者最先是将接口放在Unix操作系统里面的。如果了解Unix系统的输入和输出的话,就很容易了解Socket了。网络的
Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返
回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。

常用的Socket类型有两种:流
式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP
服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。
Socket建立为了建立Socket,程序可以调用Socket函数,该函数返回一个类似于文件描述符的句柄。socket函数原型为:int
socket(int domain, int type, int
protocol);domain指明所使用的协议族,通常为PF_INET,表示互联网协议族(TCP/IP协议族);type参数指定socket的
类型:SOCK_STREAM
或SOCK_DGRAM,Socket接口还定义了原始Socket(SOCK_RAW),允许程序使用低层协议;protocol通常赋值"0"。
Socket()调用返回一个整型socket描述符,你可以在后面的调用使用它。
Socket描述符是一个指向内部数据结构的指针,它指向描述符表入口。调用Socket函数时,socket执行体将建立一个Socket,实际上"建
立一个Socket"意味着为一个Socket数据结构分配存储空间。
Socket执行体为你管理描述符表。两个网络程序之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端
口。Socket数据结构中包含这五种信息。 socket在测量软件中的使用也很广泛

socket深层次理解

Socket编程基本就是listen,accept以及send,write等几个基本的操作。


于网络编程,我们也言必称TCP/IP,似乎其它网络协议已经不存在了。对于TCP/IP,我们还知道TCP和UDP,前者可以保证数据的正确和可靠性,
后者则允许数据丢失。最后,我们还知道,在建立连接前,必须知道对方的IP地址和端口号。除此,普通的程序员就不会知道太多了,很多时候这些知识已经够用
了。最多,写服务程序的时候,会使用多线程来处理并发访问。

我们还知道如下几个事实:

1。一个指定的端口号不能被多个程序共用。比如,如果IIS占用了80端口,那么Apache就不能也用80端口了。

2。很多防火墙只允许特定目标端口的数据包通过。

3。服务程序在listen某个端口并accept某个连接请求后,会生成一个新的socket来对该请求进行处理。

于是,一个困惑了我很久的问题就产生了。如果一个socket创建后并与80端口绑定后,是否就意味着该socket占用了80端口呢?如果是这样的,那么
当其accept一个请求后,生成的新的socket到底使用的是什么端口呢(我一直以为系统会默认给其分配一个空闲的端口号)?如果是一个空闲的端口,
那一定不是80端口了,于是以后的TCP数据包的目标端口就不是80了--防火墙一定会组织其通过的!实际上,我们可以看到,防火墙并没有阻止这样的连
接,而且这是最常见的连接请求和处理方式。我的不解就是,为什么防火墙没有阻止这样的连接?它是如何判定那条连接是因为connet80端口而生成的?是
不是TCP数据包里有什么特别的标志?或者防火墙记住了什么东西?

后来,我又仔细研读了TCP/IP的协议栈的原理,对很多概念有了更深
刻的认识。比如,在TCP和UDP同属于传输层,共同架设在IP层(网络层)之上。而IP层主要负责的是在节点之间(End to
End)的数据包传送,这里的节点是一台网络设备,比如计算机。因为IP层只负责把数据送到节点,而不能区分上面的不同应用,所以TCP和UDP协议在其
基础上加入了端口的信息,端口于是标识的是一个节点上的一个应用。除了增加端口信息,UPD协议基本就没有对IP层的数据进行任何的处理了。而TCP协议
还加入了更加复杂的传输控制,比如滑动的数据发送窗口(Slice
Window),以及接收确认和重发机制,以达到数据的可靠传送。不管应用层看到的是怎样一个稳定的TCP数据流,下面传送的都是一个个的IP数据包,需
要由TCP协议来进行数据重组。

所以,我有理由怀疑,防火墙并没有足够的信息判断TCP数据包的更多信息,除了IP地址和端口号。而且,我们也看到,所谓的端口,是为了区分不同的应用的,以在不同的IP包来到的时候能够正确转发。

TCP/IP只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接口。就像操作系统会提供标准的编程接口,比如Win32编程接口一样,TCP/IP也必须对外提供编程接口,这就是Socket编程接口--原来是这么回事啊!

在Socket编程接口里,设计者提出了一个很重要的概念,那就是socket。这个socket跟文件句柄很相似,实际上在BSD系统里就是跟文件句柄一
样存放在一样的进程句柄表里。这个socket其实是一个序号,表示其在句柄表中的位置。这一点,我们已经见过很多了,比如文件句柄,窗口句柄等等。这些
句柄,其实是代表了系统中的某些特定的对象,用于在各种函数中作为参数传入,以对特定的对象进行操作--这其实是C语言的问题,在C++语言里,这个句柄
其实就是this指针,实际就是对象指针啦。

现在我们知道,socket跟TCP/IP并没有必然的联系。Socket编程接口在设计的
时候,就希望也能适应其他的网络协议。所以,socket的出现只是可以更方便的使用TCP/IP协议栈而已,其对TCP/IP进行了抽象,形成了几个最
基本的函数接口。比如create,listen,accept,connect,read和write等等。

现在我们明白,如果一个程
序创建了一个socket,并让其监听80端口,其实是向TCP/IP协议栈声明了其对80端口的占有。以后,所有目标是80端口的TCP数据包都会转发
给该程序(这里的程序,因为使用的是Socket编程接口,所以首先由Socket层来处理)。所谓accept函数,其实抽象的是TCP的连接建立过
程。accept函数返回的新socket其实指代的是本次创建的连接,而一个连接是包括两部分信息的,一个是源IP和源端口,另一个是宿IP和宿端口。
所以,accept可以产生多个不同的socket,而这些socket里包含的宿IP和宿端口是不变的,变化的只是源IP和源端口。这样的话,这些
socket宿端口就可以都是80,而Socket层还是能根据源/宿对来准确地分辨出IP包和socket的归属关系,从而完成对TCP/IP协议的操
作封装!而同时,放火墙的对IP包的处理规则也是清晰明了,不存在前面设想的种种复杂的情形。

最新文章

  1. (转)C#调用默认浏览器打开网页的几种方法
  2. 机器学习系列:python
  3. CSS样式选择器优先级
  4. Linux 服务器的网络配置 - 1. 查看 Linux 服务器的网络连接
  5. iOS真机调试问题-App installation failed,The maximum number of apps for free development profiles has been reached.
  6. Android中Service深入学习
  7. slots - Python的结构体 转
  8. pwm最后的解释
  9. 【Python3之pymysql模块】
  10. ubuntu 14.04搭建PHP项目基本流程
  11. 接收JSON类型转成对象
  12. bzoj 4501 旅行
  13. Mockito单元测试实战
  14. CodeForces - 363D --二分和贪心
  15. iOS UI布局-VFL语言
  16. Redis 可视化界面工具:Fastoredis
  17. 在Eclipse中运行JAVA代码远程操作HBase的示例
  18. Material Designer的低版本兼容实现(六)—— Ripple Layout
  19. 使用JS和JQuery 阻止表单提交的两种方法
  20. MVC阻止用户注入JavaScript代码或者Html标记

热门文章

  1. 小白从零开始阿里云部署react项目+node服务接口(三:部署到服务器)
  2. Linux常用命令(学习笔记)
  3. 利用python实现平稳时间序列的建模方式
  4. NIO入门之缓冲区Buffer
  5. vue学习(十六) 自定义私有过滤器 ES6字符串新方法 填充字符串
  6. Python学习手册(第4版)PDF高清完整版免费下载|百度云盘
  7. SQL语法入门
  8. xctf-web supersqli
  9. 番外:socketserver用法
  10. 2020年最新.NET面试题