Socket

2024-06-25

Socket(精选10篇)

Socket 篇1

摘要:利用Java实现网络文件传输, 实现客户端和服务器端之间的上传和下载。在客户端可以选择本地磁盘的所有文件进行上传, 但是只能下载服务端共享文件。本次实现在JDK1.5环境下进行开发, 整个实现基于Socket编程。

关键词:上传,下载,Socket编程,传输,客户端

传统的网络编程是一项非常细节化的工作, 程序员必须处理和网络有关的大量细节, 甚至有些需要理解网络相关的硬件知识。但是Java则将这些细节予以屏蔽, 使得操作网络数据传输像操作流一样简单方便。

到底什么是Socket?简单来说, Socket就是网络上的两个程序现实数据交换的双向链路, 即实现客户端和服务端的连接。一个Socket由一个IP地址和一个端口号唯一确定。

Socket的整个通讯过程可以描述如下:Server端Listen (监听) 某个端口是否有连接请求, Client端向Server端发出Connect (连接) 请求, Server端向Clien端发回Accept (接受) 消息。一个连接就建立起来了。Server端和Client端都可以通过Send, Write等方法与对方通信, 见图1。

正是由于Java的Socket网络编程如此简单方便, 因此选择基于Socket实现网络上文件的传输。

1 实现方案

对于客户端而言, 工作首先为连接服务端, 如果连接成功可以从本地磁盘选取任何一个文件上传至服务端或者从服务端下载任何共享的文件。如果上传和下载工作完毕可以断开连接。按下返回按钮可以返回到上级目录。双击鼠标将显示下一级目录和文件。如果双击的是文件, 则不会产生任何结果。当然在此过程中需要考虑各种异常的出现。客户端功能, 见图2。

对于服务端而言, 主要的工作是进行监听, 一旦监听到有请求, 将接收请求并创建一个Socket与客户端建立连接, 并能浏览所有共享的文件, 如果任务完成可以切断连接, 当然在此过程中需要考虑各种异常的出现。服务端功能见图3。

在设计的时候运用设计模式来提高程序的可扩展性。采用了装饰模式, 利用此模式可以扩充一个对象的功能, 当然这种扩展不是通过子类机制扩展, 而是通过另一个新对象动态地、透明地包装现有对象;界面采用了复合模式和策略模式, 利用这两种模式可以使容器中装纳组件和界面的绝对定位。

1.1 客户端的实现

客户端主要用来完成文件的上传、下载和显示目录功能。每执行一个动作需向服务端发送命令。服务端的共享文件在客户端是以目录树显示, 在目录树中如果是文件夹可以双击扩展其节点, 当然还可以返回上一级目录。下面介绍关键类。

1.1.1 类Client Interface

客户端界面类, 客户端界面包括的组件有:3个JText Field实例, 分别用来输入主机地址、用户名和密码。4个按钮分别处理连接、上传、下载和返回上一级目录。1个分隔窗格用来存放服务器的目录树。1个滚动窗格放在分隔窗格中, 分隔窗格中还放有JFile Chooser的一个实例。其中所包含的方法如下。

expansion (int x, int y) :当双击目录树中的目录查看下一级文件和目录时调用此方法, 参数x和y表示鼠标双击的位置, 根据位置得到双击的文件夹, 由JTree的方法get Closet Path For Location (x, y) 实现。将所得到的文件夹的路径传送给服务端, 服务端再将其下的所有文件和目录传送给客户端, 客户端调用accept Files () 方法接收文件并将其显示为一棵目录树。

display () :将界面的各个组件定位, 采用绝对定位, 并定义内部类Action Listener实现Action Listener, 此类是按钮的事件监听器, 并将类Action Listener1的实例注册到各个按钮。

get Conn (String str, int port) :此方法向服务端申请建立连接, 一旦连接成功则将以目录树的形式显示服务端下的目录和文件。传输过程中以所接收的字符是否等于-2来判断, 若为-2表明传输结束。

Down () :用来处理下载文件。接收文件流是以字节数组做缓冲, 并在本地当前目录生成同名文件, 判断接收是否完毕是以接收到的字节数是否等于-1。

up Load () :此方法用来上传文件, 发送up Load命令和所要上传的文件和文件所要保存的位置, 然后建立上传文件的文件流, 以字节数组做缓冲传送给服务端, 以计数变量amount是否小于零来判断文件是否已读完, 最后刷新目录, 将所传文件在目录树上显示。

up () :此方法用来返回上一级目录, 根据变量path Name到当前目录的上一级目录, 然后向服务端发送要求扩展此目录的命令, 即可返回上一级目录。

1.1.2 类Client

顶层类, 设置了观感, 并生成了类Cliet Interface的实例win, 调用其display () 方法。

1.2 服务器端的实现

服务器必须考虑并发性, 为了更进一步提高系统的可伸缩性, 运用线程池来提高程序的效率。下面介绍关键类。

1.2.1 Closed Queue Exception类

继承Exception类, 用户自定义异常。

1.2.2 Blocking Queue类

由工具类Linked List实例list存放线程。其中add () 方法向队列加入线程, notify () 唤醒正在等待的线程, get () 从队列中取线程, 当队列为空时则等待, size () 得到队列的长度, close () 设置线程池状态为false, 并唤醒等待线程, 同时将队列清空。方法add () 、get () 、size () 和close () 需实现同步。

1.2.3 Thread Pool类

此类用于定义线程池, 其中有一个内部类Thread Pool Thread称为工作线程, 由工作线程不停地取队列中的线程运行。属性有:max Pool Size表示线程池的最大值, init Pool Size表示线程池的初始值, is Running表示线程池的状态, request Queue用来存放线程, queue Requests表示队列元素的计数变量。

1.2.4 Thread Pool Thread类

此类是Thread Pool Thread的内部类, 继承了Thread类, 重定义了run () 方法, 并在run () 方法中调用reqeust Queue中的线程并调用其start () 方法, 前提条件是线程池状态为true且当前线程没被中断, 捕捉异常Interrupted Exception。

1.2.5 Listening类

此类用于监听客户端是否发送请求。

构造方法Listening ()

server Socket=new Server Socket (3456) ;

pool=new Thread Pool (5) , 并捕捉异常IOException。

run () 方法

while (true) {

try{

p o o l.s u b m i t R e q u e s t (n e w D i s p o s a l T h r e a d (server Socket.accept () ) ) ;

}

catch (IOException exc) {…}

1.2.6 Diaposal Thread类

此类继承Thread类, 用于处理客户端传送的命令。包含如下方法。

run () 方法:根据不同的命令执行不同的操作。

transfer Files (String file Name) :此方法用来传送文件和目录到客户端, 在传送过程中判断是文件还是目录, 如果是目录则在目录名后加上[str], 文件传输完毕以-2做为结束标志。参数file Name表示在客户端浏览到服务器的当前目录。

1.2.7 Server Interface类

此类用于做服务器端界面。服务端有三个按钮:浏览、开始和停止。浏览按钮用来选择可供用户所共享的文件夹, 默认为d:;当单击“开始”按钮, 创建类Listening的一个实例, 并调用start () 方法;当单击“停止”按钮, 调用线程池的shut Down () 方法。

2 技术解析

利用网络进行文件传输是当今用的非常广的技术, 为更好地提高文件传输的效率和准确率, 在设计过程中用到如下技术:为了提高服务器端效率, 同时也为了实现多用户并发执行, 服务器端采用多线程, 同时应用线程池能提高程序的伸缩性。读写本地文件及对网络的读写操作中都使用了流技术。运用多种设计模式来实现可重用代码、使代码更容易被他人理解、保证代码可靠性。在此设计中合理运用设计模式可以更完美地解决许多问题。在服务端程序中, 自定义了异常, 在传输过程中也充分利用了已有的异常机制, 以保证程序的健壮性。

3 结语

利用Socket实现网络文件传输, 可以实现跨平台, 能更好地实现移植。采用的是图形用户界面, 操作简单。利用多种设计模式使程序的实现更加完美, 服务器端利用线程池提高程序效率。

参考文献

[1]刘德山, 金百东.Java设计模式深入研究[M].北京:人民邮电出版社, 2014:7.

Socket 篇2

用golang不用他的net包还有什么意义,这里提供一个测试代码:

server.go 服务端:

代码如下:

package main

import (

“fmt”

“log”

“net”

“bufio”

)

func handleConnection(conn net.Conn) {

data, err := bufio.NewReader(conn).ReadString(‘n‘)

if err != nil {

log.Fatal(“get client data error: ”, err)

}

fmt.Printf(“%#vn”, data)

fmt.Fprintf(conn, “hello clientn”)

conn.Close

}

func main() {

ln, err := net.Listen(“tcp”, “:6010”)

if err != nil {

panic(err)

}

for {

conn, err := ln.Accept()

if err != nil {

log.Fatal(“get client connection error: ”, err)

}

go handleConnection(conn)

}

}

client.go 客户端:

代码如下:

package main

import (

“fmt”

“net”

“bufio”

)

func main() {

conn, err := net.Dial(“tcp”, “:6010”)

if err != nil {

panic(err)

}

fmt.Fprintf(conn, “hello servern”)

data, err := bufio.NewReader(conn).ReadString(‘n‘)

if err != nil {

panic(err)

}

fmt.Printf(“%#vn”, data)

}

Socket 篇3

关键词:SOCKET;计算机远程控制

中图分类号:TP273.5文献标识码:A文章编号:1007-9599 (2012) 02-0000-02

Computer Remote Control Based on SOCKET Technology

Chen Shijun

(Hubei Telecom Business Technology,Support Center,Wuhan430015,China)

Abstract:Today,the computer network has become an integral part of human social life,which the computer's remote control system is to play a role in promoting the advancement of society as a whole.In addition to in addition to the production of industrial automation,computer remote control system is also widely used in office,technical support and other aspects.In this paper,design a simple SOCKET technology based on computer remote control system.

Keywords:SOCKET;Computer remote control

一、远程控制系统的意义及理论基础

(一)远程控制系统的意义

计算机远程控制对于整个互联网络而言具有重要的意义,无论是正面意义的远程技术支持还是反面意义的后门犯罪从发展的角度来看都对计算机及网络技术起到了一个推动作用,而科学技术是第一生产力,技术的进步对于整个社会来说就有意义,尤其是现在的计算机已经渗透到人们生活中的每一个角落,所以本文吸收以往的一些远程控制系统的优点并结合自己的理念设计了一套基于SOCKET技术的计算机远程控制系统。

(二)远程控制系统的理论基础

本文设计的远程控制系统是基于SOCKET的,也就是俗称的“套接字”,使用SOCKET有以下优点:

1.减少了网络通信的技术难度,SOCKET有标准的函数支持,具有标准的使用方法。

2.可以轻松的实现跨平台,目前基本所有的系统,windows、linux、unix及嵌入式系统、PLC等全部支持SOCKET。

综上所述,基于SOCKET设计计算机远程控制系统是可行的。

二、遠程控制系统的整体构架

(一)传输协议的选择

在TCP/IP的传输层上,存在着两种可以使用的通信协议,一种是UDP,另一种是TCP。UDP协议能够提供的是一种不可靠的服务,不可能保证数据在传输过程中不出现差错;TCP协议是一种能提供双向有序、且保证数据包可靠收发的协议。在远程控制系统中,安全是第一个要考虑的问题,所以本文设计的远程控制系统使用TCP作为传输协议。

(二)使用模型的选择

本文设计的远程控制模式为一控多,既由一台主计算机控制其他计算机,在模型上更加贴近于C/S模型,虽然使用C/S模型增加了客户端程序设计的难度,但是C/S处理数据快速、准确、安全、封闭性能好,可以很好的抵抗干扰,并且可以快速的响应远程操作请求,所以本系统使用C/S模型。

(三)控制端需求设计

控制端要求有以下三点:

1.能向指定的被控端发送操作指令。在指令中包含两个部分:一是被控端地址,二是操作代码。

2.可接受被控端返回的信息。当控制端受到被控端返回的信息时应该能分析出该信息的来源是否正确,数据包结构是否合法,并能将合法的数据包解析为可理解的信息呈现给控制者。

3.可以提供数据加密服务。为了更好的保证系统的安全性,必须使用一套安全可靠的密码机制,所以要求控制端应该能与被控端建立可靠的安全的连接,并用该链接传输加密后的数据包。

(四)被控端需求设计

被控端主要承担四个工作:

1.对控制端发送过来的操作代码的解析与执行。要求被控端可以验证操作代码来源,分析操作代码是否合理,合理的话要求被控端可以执行控制端要求的操作。

2.将操作结果反馈给控制端。要求被控端必须收集每一步操作产生的日志信息,当控制端需要查看结果时,可以将信息传递回控制端。

3.提供数据加密服务。被控端的数据加密服务与控制端的数据加密服务目的相同,但是实现方法有差别,两者代码部分重合,但并不通用。

4.提供自我保护服务。避免被控端误操作脱离控制端的控制。

三、控制端具体设计

(一)控制端工作使用线程如下

1.常驻监听线程,用以打开一个指定的端口,对该端口进行监听,等待由被控端主动发起的连接请求。

2.图形界面,用做与控制者交互,使用该界面与其他服务线程联系并且作为操作者操作翻译、确认以及显示接受到的由被控端发送的数据内容。在面向使用者的设计中,图形界面可完成以下任务:

(1)连接到指定的被控端IP。(2)显示连接列表。(3)断开与某被控端的IP。(4)向某被控端发送操作命令,操作指令可以是以下内容:直接交由被控端执行的命令,此类命令既可以人工键入,也可由软件自动生成。控制被控端返回状态的命令。(5)显示被控端状态。可以是图像,文字等。

3.加密服务线程,由图形界面临时创立,负责接受图形界面发送过来的用户操作编码,并将其根据传输通道建立时随机产生的密钥进行加密或解密操作,图形界面会根据使用需求不同传递进不同的参数,该线程会根据参数选择是加密后送入传输线程发送还是加密后向图形界面返回明文。其基本流程如下:

首先检查图形界面传递进的参数含义是加密还是解密,如果是加密则将图形界面传递的参数对指定数据进行加密,加密后的数据直接送入传输线程;如果是解密,则对指定数据解密,之后返回解密后的数据地址指针以及数据长度。

4.传输线程,该线程负责使用建立的传输通道传送数据,由图形界面创立,当常驻监听线程监听到被控端连接请求并交给图形界面同意后或者由使用者操作图形界面直接发起向被控端连接的请求同意后创立,该线程的基本流程如下:

首先该线程打开特定端口与被控端建立明文连接,之后建立安全通道建立线程建立安全通道,当通道建立后既进入等待中,其生命周期从建立开始到控制者操作图形界面停止与被控端连接为止。。

5.安全通道建立线程,由传输线程建立。发起连接者不同,建立条件也有差异。其操作流程如下:

首先被控端使用控制端公钥加密得到的随机对称式密钥K1并发送至控制端,之后控制端使用公钥解密得到K1并用K1加密K1,将密文发送至被控端,然后被控端用K1解密密文并与K1进行比较,判断是否正确,如果正确,那么建立连接,使用的通信密钥为K1。如果由连接请求是由控制端发起,则多加一个控制端要求被控端发起连接的公开请求过程。

四、被控端具体设计

被控端与控制端有着诸多的相同点,包括常驻监听线程、加密服务线程、传输线程、安全通道建立线程。不同的是被控端没有图形界面,所有的操作全部为后台进行,而且被控端多加了自我保护服务,用以保护被控端的可控性。其不同的地方设计如下:

(一)后台操作线程。该线程起到的功能相当于控制端的图形界面所起到的中枢功能。当该线程接受到控制端发送过来的指令时,首先做的也是解密翻译,之后根据命令的不同执行不同的操作。操作有以下几类:

1.直接交由操作系统执行命令并记录返回情况;2.控制计算机的输入设备并记录返回情况;3.控制计算机的输出设备并记录返回情况;4.向控制端发送记录的返回情况。

(二)自我保护线程。该线程设计运行于计算机的RING0层,并运用ROOKIT手法以及软件安全技术屏蔽一切对本线程不利的操作,用以保证被控端的可控性。其监控方面有以下几个:

1.计算机驱动的加载;2.输入输出设备;3.文件系统变动;4.应用程序的危险操作。

通过以上的防护措施,基本上可以保证控制端对于被控端的控制,达到远程控制的目的。

参考文献

[1]田鹏.基于WEB的远程控制系统设计[D].兰州大学,2011

[2]马强.计算机网络远程控制系统的研究与应用[D].中国地质大学,2007

[3]王涛.基于安全模式的软件安全设计方法[D].吉林大学,2011

[4]朗波,王晓青.基于计算机网络远程控制系统的图像传输实现策略[J].青海大学学报(自然科学版),2008

[5]朱庆军,丁志刚,吕卫阳.基于C/S模式的智能相机远程控制系统研究[J].电气应用,2008(08)

Socket 篇4

即时通讯 (Instant Messenger) 是一种基于互联网的实时通讯方式[1]。早在1996 年, ICQ即在全球发布, 其发布之初只有简单的发送和接收消息功能。时至今日, 即时通讯工具早已成为互联网上成熟的软件, 它的功能不再局限于简单的收发信息[2,3]。像国内的腾讯QQ, 集语音视频聊天、文件传输、远程桌面、游戏、网上交友和空间社区于一身, 已不再是一个简单的聊天工具了。借助即时通讯软件, 人们可以不受地域限制的面对面交流, 在方便交流的同时也极大地提高了效率, 成为现代生活中不可或缺的一部分[4,5]。

1 Socket套接字编程

Socket简单来说就是通信双方的一种约定, 在应用程序和网络驱动中扮演桥梁角色, 用套接字中的相关函数来完成通信过程[6]。其具体使用方法是:在应用程序中创建Socket, 并绑定操作和驱动程序, 以此建立双方的联系;当要实现通信时, Socket接收应用程序的数据, 交给驱动程序通过网络发出, 另一端的主机接收该Socket所绑定的IP地址和端口号等数据, 再由驱动程序交给Socket, 此时应用程序从中提取接收到的数据 (主要是IP地址和端口号) , 然后确认连接。这样就完成了一次在网络上两台主机通过Socket发送和接收数据。由于在网络上通信存在两种通信方式, 即TCP/UDP通信方式[7]。在进行两个程序之间的通信时, 其使用的通信方式必须统一, 不能一端使用TCP协议, 一端使用UDP协议[8]。

2 系统设计与实现

2.1 系统设计

系统分两部分, 由客户端和服务器端组成。

2.1.1 服务器端

服务器端主要完成3 大功能:建立连接、断开连接以及监听客户请求。

(1) 建立连接。在系统启动时就要建立连接, 之后服务器端会绑定本地计算机的一个端口, 之后会监听是否有客户端进行请求连接的操作以及是否要断开连接。

(2) 断开连接。关闭监听窗体, 系统断开连接。

(3) 监听客户请求。服务器端在这里起到了信息快速处理和响应枢纽的作用, 客户端请求服务都要与服务器端发生信息交流, 向服务器端请求的客户端的信息都会被传到服务器端。服务器会对客户端的请求进行判断, 如果其合法的话, 服务器端会按客户端的要求发送出去, 这时客户端可以向服务器端发送操作请求, 如:添加好友、获取分组等;否则, 返回请求不合法。

2.1.2 客户端

客户端完成以下六大功能:

(1) 用户注册。客户端与服务器建立连接, 创建完成通信通道, 这时会接收服务器的监听。通过系统的注册界面, 输入账号和密码, 完成注册。

(2) 用户登录。客户端与服务器连接成功之后, 会通过通信通道进行信息上的交流。用户在系统软件的“登录界面”上输入账号以及密码, 在这个过程中, 服务器端一直对客户端实施监听并且判断其请求是否合理。如果服务器端对用户信息验证通过, 客户端会打开程序的主界面。

(3) 添加好友或分组。用户在登录系统之后可以进行添加好友和分组的相关操作。

(4) 删除好友或分组。用户可以选择进行删除好友和分组的相关操作。

(5) 聊天功能。客户在与好友建立通信连接后, 便可以与好友进行聊天, 聊天时发送的是文本信息。

(6) 文件传输。用户之间可以相互传送文件以实现文件共享。

图一所示为具体的系统功能模块。

2.2 系统实现

2.2.1 服务器实现

(1) 打开一个通信通道 (本机的某一端口地址) 并告知本地主机, 它将在某一公认端口号上接收客户请求。

(2) 等待客户请求到达该端口。

(3) 接收到重复服务请求, 处理该请求并发送应答信号。服务完成后, 关闭此进程与客户端的通信链路并终止。

(4) 返回第二步, 等待另一客户请求。

(5) 断开服务器。

2.2.2 客户实现

(1) 打开一个通信通道, 并连接到服务器所在主机的特定端口 (可以通过所在服务器的IP地址来进行连接) 。

(2) 向服务器发送服务请求。

(3) 等待服务器端做出相应的处理并接收应答;继续提出请求。

(4) 请求结束后关闭通信通道并终止连接。

2.3 基于UDP (面向无连接) 的Socket编程

2.3.1 服务端

(1) WSAStart加载套接字库;

(2) 创建Socket () 函数;

(3) 利用bind () 函数绑定本机的IP地址和端口号;

(4) recvfrom () 函数将接收来至客户端的请求;

(5) Sendto () 函数发送信息;

(6) close () 关闭Socket。

2.3.2 客户端

(1) WSAStart加载套接字库;

(2) 在客户端创建Socket () 函数;

(3) Sendto () 向服务端发送数据;

(4) 使用recvfrom () 函数接收服务端数据;

(5) 当连接需要中断时使用close () 函数断开连接。

图二所示为服务器端和客户端调用流程。

2.4 系统运行结果

系统主要采用MFC来完成。待双方添加好友成功后, 双击好友就可以进行即时通讯了。图三所示为通讯界面。

3 结束语

本文介绍了运用Socket套接字编程和网络编程完成即时通讯软件, 实现了局域网中即时聊天、聊天室聊天、视频聊天和文件传输等功能, 最后经过测试和优化, 该软件运行稳定。

参考文献

[1]RB Jennings, EM Nahum, DP Olshefski.A study of internet instant messaging and chat protocols[J].IEEE Network, 2006, (20) .

[2]谌颃.一种多功能网络即时通讯系统的设计[J].网络安全技术与应用, 2014, (11) :62.

[3]雷东升.网络即时通讯系统[J].计算机与现代化, 2008, (04) :51-53.

[4]张磊, 王贞化.基于TCP下多线程WINSOCK编程[J].科技广场, 2006, (07) :51-53.

[5]刘彬, 赵荣彩, 丛建刚.即时通信协议分析与监控技术研究[J].计算机应用研究, 2007, 24 (09) :260-262.

[6]李延松, 余隋怀, 吴博.基于Socket的安全即时通讯软件的设计[J].科学技术与工程, 2007, 7 (12) :2974-2977.

[7]赵辉, 邓正伟, 宋婵.基于局域网的即时通讯系统的设计与实现[J].兵工自动化, 2007, 26 (10) :52-54.

Go语言实现socket实例 篇5

用golang不用他的net包还有什么意义,这里提供一个测试代码:

server.go 服务端:

代码如下:

package main

import (

“fmt”

“log”

“net”

“bufio”

)

func handleConnection(conn net.Conn) {

data, err := bufio.NewReader(conn).ReadString(‘‘)

if err != nil {

log.Fatal(“get client data error: ”, err)

}

fmt.Printf(“%#v”, data)

fmt.Fprintf(conn, “hello client”)

conn.Close()

}

func main() {

ln, err := net.Listen(“tcp”, “:6010”)

if err != nil {

panic(err)

}

for {

conn, err := ln.Accept()

if err != nil {

log.Fatal(“get client connection error: ”, err)

}

go handleConnection(conn)

}

}

client.go 客户端:

代码如下:

package main

import (

“fmt”

“net”

“bufio”

)

func main() {

conn, err := net.Dial(“tcp”, “:6010”)

if err != nil {

panic(err)

}

fmt.Fprintf(conn, “hello server”)

data, err := bufio.NewReader(conn).ReadString(‘‘)

if err != nil {

panic(err)

}

fmt.Printf(“%#v”, data)

}

Socket 篇6

1 Socket通信流程

Socket是“打开—读/写—关闭”模式的实现, 其通信流程如下:

(1) 服务器根据地址类型 (ipv4, ipv6) 、Socket类型, 协议创建Socket;

(2) 服务器为Socket绑定IP地址和端口号;

(3) 服务器Socket监听端口号请求, 随时准备接收客户端发来的连接, 这时服务器的Socket并没有被打开;

(4) 客户端创建Socket;

(5) 客户端打Socket, 根据服务器IP地址和端口号试图连接服务器Socket;

(6) 服务器Socket接收到客户端Socket请求, 被动打开, 开始接收客户端请求, 直到客户端返回连接信息。这时Socket进入阻塞状态, 所谓阻塞即accept () 方法一直到客户端返回连接信息后才返回, 开始接收下一个客户端谅解请求;

(7) 客户端连接成功, 向服务器发送连接状态信息;

(8) 服务器accept方法返回, 连接成功;

(9) 客户端向Socket写入信息;

(10) 服务器读取信息;

(11) 客户端关闭;

(12) 服务器端关闭。

2 建立Socket通信

Socket主要由客户端和服务端两部分构成, 通过服务端与客户端建立通信后, 由服务端向客户端发送相关的指令。

(1) 在服务端, 首先需要申请一个Socket, 然后把它绑定到一个IP地址和一个端口, 开启监听, 等待客户端发来的接收连接。

(2) 在客户端, 也需应该申请一个Socket, 然后连接到服务器的指定IP和端口。

(3) 服务器端接收到连接请求后, 产生一个新的Socket (端口大于1024) 与客户端建立连接并进行通信, 原监听Socket继续监听。

(4) 需要注意一点的是负责通信的Socket是不能无限创建的, 创建的数量和操作系统是有关系的。

3 基于Socket的无线视频传输

利用Socket和Wi Fi技术进行视频传输, 需将捕获到的每帧图像进行转码, 转成适合Socket传输的byte数组的形式, 然后通过Socket通信, 在客户端接收从服务端传送过来的视频, 并进行实时显示。

(1) 在服务端通过调用Marshal类的成员copy函数, 把Image<Bgr, Byte>类型的图片的尺寸转换到byte数组中, 然后发送通过Socket传输发送byte数组到客户端, 这部分C#指令如下:

(2) 在客户端通过Socket传输接收到来自服务端的数组byte数组, 并通过格式转换, 提取数据, 还原成image Box控件能够显示的Image<Bgr, Byte>类型, 然后就能偶在客户端显示服务端接收到视频了。相关的格式转换代码如下:

(3) 调试成功后, 打开服务端和客户端的运行程序, 然后, 点击服务端的Start Server按键, 开启服务, 在客户端点击点击连接, 使服务端与客户端建立通信, 然后在服务端点击Start Capture后, 服务端会接收到本地摄像头的视频, 客户端接收的画面与服务端一致, 视频传输完成。

摘要:详细介绍了Socket通信流程。通过建立Socket通信, 对视频图像进行转码, 利用WiiF技术传输mjpg格式视频流, 在C#制作的客户端能够有效接收视频画面。

关键词:Socket通信,无线,视频传输

参考文献

[1]高伟, 詹胜.基于Socket接口网络通信的实现[J].唐山师范学院学报, 2008 (05) :19-20.

Socket 篇7

Linux是一个免费的类Unix操作系统,最初是由芬兰人Linus Torvalds于1991年开发。Linux操作系统具有良好的稳定性以及强大的网络功能。Linux系统平台被广泛应用到网络通信程序的开发中。网络通信编程要用到网络套接字(Socket)。Socket是一种描述符,它是网络通信的基本操作单元。数据传输是一种特殊的I/O,提供了不同主机间的进程互相通信的端点,这些进程在通信前各自建立一个Socket,并通过对Socket的读写操作实现网络通信的功能。

1 Socket工作原理

Socket为套接字,是一种双向的通信端口。网络程序设计全靠套接字接受和发送信息。Socket的英文原意就是“孔”或“插座”,现在,作为BSD UNIX的进程通讯机制,取其后一种意义。日常生活中常见的插座,有的是信号插座,有的是电源插座,有的可以接受信号(或能量),有的可以发送信号(或能量)。假如电话线与电话机之间安放一个插座(相当于二者之间的接口,这一部分装置物理上是存在的)则Socket非常相似于电话插座。

图1为使用socket进行通信的示意图。Socket通信与打电话具有相似之处,电话的通话双方相当于相互通信的两个进程;通话双方所在的地区(享有一个全局惟一的区号)相当于一个网络,区号是它的网络地址。例如,用户甲要给用户丁打电话,在通话之前,用户甲必须要使用一部电话机,这部电话机就对应有一个Socket号;同时要知道用户丁的电话号码,相当于对方有一个Socket。然后向用户丁拨电话,相当于发出连接请求。如果用户丁在场并且处于空闲状态(相当于通信的另一主机开机且可以接受连接请求),拿起电话话筒,双方就可以正式通话,相当于连接成功。双方通话的过程,是向电话机发出信号和从电话机接受信号的过程,相当于向Socket发送数据和从Socket接受数据。通话结束后,一方挂起电话机,相当于关闭Socket,撤消连接。在电话系统中,通信的双方只需要知道本地电话机和对方电话号码就可以了,其他的相关通信设施并不需要知道,这一点与Socket机制非常相似。Socket利用网间通信设施实现进程通信,但它对通信设施的细节毫不关心。

通过以上的例子,可以得出Socket实质上是提供了进程通信的端点。进程通信之前,双方首先必须各自创建一个端点,否则是没有办法建立联系并相互通信的。正如打电话之前,双方必须各自拥有一台电话机一样。但是这时候会出现一个现象:进程通信时,如何来确认接收到的数据所要发送的进程。譬如,当用户甲给用户丁打电话,当用户丁所在的电话响后,当接电话的不是用户丁时,用户甲肯定会说:“我找用户丁,请帮我转接一下”。那么在进程通信中是如何实现的呢?需要一种标识信息,用于描述网络通信数据发往的进程。TCP/IP协议提出了协议端口的概念,用于标识通信的进程。当进程与某个端口绑定后,操作系统会将收到的给该端口的数据发往该进程。与文件描述符类似,每一个端口都有被称为端口号的整数类型的标识符,该标识符用于区分不同的端口。不同的协议可以使用相同的端口号进行数据传输。例如,TCP使用了344的端口号,UDP同样也可以使用344端口号进行数据传输。端口号为一个16位的无符号整数,其取值范围为0-65535。低于256的端口被作为系统的保留端口号,主要用于系统进程的通信,不在这一范围的端口号被称为自由端口号,可以由进程自由使用。每一个Socket都用一个半相关描述:{协议,本地地址,本地端口},一个完整的Socket则用一个相关描述{协议,本地地址,本地端口,远程地址,远程端口}。每一个Socket有一个本地的惟一Socket号,由操作系统分配。最重要的是,Socket是面向客户-服务器模型而设计的,针对客户和服务器程序提供不同的Socket系统调用。客户随机申请一个Socket号(相当于一个想打电话的人可以在任何一台入网的电话上拨叫呼叫);服务器拥有全局公认的Socket,任何客户都可以向它发出连接请求和信息请求(相当于一个被呼叫的电话拥有一个呼叫方知道的电话号码)。

Socket利用客户-服务器模式巧妙的解决了进程之间建立通信连接的问题。服务器Socket为全局所公认非常重要。两个完全随机的用户进程之间,因为没有任何一方的Socket是固定的,就像打电话却不知道别人的电话号码,要通话是不可能的。

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

Socket接口设计者最先是将接口放在Unix操作系统里面的。如果了解Unix系统的输入和输出的话,就很容易了解Socket。网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。

2 Socket程序设计

套接字有三种类型,其中流式套接字可以实现可靠的数据传输。根据套接字类型的不同,套接字通信又分为面向连接的通信和无连接的通信。面向连接的套接字通信使用的协议为TCP协议。该协议可以保证数据的可靠传输,当然这一可靠性是以一定的性能损失为代价的。无连接的套接字通信方式使用UDP协议。对比面向连接的套接字通信,这一方式无需在客户机与服务器之间建立连接,所以使用这一方式无法保证数据的可靠传输。网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端。网络程序是先有服务器程序启动,等待客户端的程序运行并建立连接。一般的来说是服务端的程序在一个端口上监听,直到有一个客户端的程序发来了请求,服务器端根据该请求提供相应的服务。图2为套接字的工作流程。为了实现服务器与客户机间的通信,服务器与客户机都必须创建套接字。服务器在创建套接字后,需要指定监听的端口来等待客户机,因此,还有绑定端口号的操作。之后,服务器将处于监听状态,等待客户机来连接指定端口。当接收到客户机的连接请求后,服务器调用Accept函数来建立与客户机间的通信。在成功建立通信后,就可以通过Read函数或Write函数进行通信。客户端处的流程与服务器相比,简单一些。客户端在创建套接字后,调用Connect函数去连接服务器指定的端口。在服务器接收连接后,客户机与服务器之间就可以通过Write函数和Read函数实现数据通信了。

3 程序实例分析

通过设计客户机/服务器模式程序来进一步深入分析socket通信原理。server.c和client.c使用流套接字将服务器的信息传递给客户机。server.c为服务端的实现。首先创造建套接字,通信域为PF_INET,然后调用bind函数将指定的端口等到信息与套接字关联起来,调用listen函数实现对指定端口的监听。当有连接请求时,通过调用accept函数建立与客户机的连接,最后调用write和read函数来与客户机进行信息交换。client.c为客户端程序,实现较为简单。首先调用connect函数来连接指定的服务器和端口,然后通过write函数和read函数来实现与服务器之间的通信。

使用gcc编译server.c和client.c,获得可执行文件serve和client。

先执行server,然后运行client。./server portnumber&(portnumber随便取一个大于1204且不在/etc/services中出现的号码就用8888好了),然后运行。

4 结束语

在Linux系统中,不同主机或相同主机之间的不同进程可以通过套接字实现通信。套接字通信是一种服务器/客户机模型的通信方式。面向连接的套接字通信使用的协议为TCP协议。该协议可以保证数据的可靠传输,当然这一可靠性是以一定的性能损失为代价的。通过设计服务器端和客户端程序,使用流套接字实现了网络中主机间的面向连接通信。

参考文献

[1]朱居正,高冰.Red Hat Enterprise Linux网络管理[M].北京:清华大学出版社.2005.

[2]张轶博,孙占峰.Linux应用大全[M].北京:机械工业出版社.2000.

[3]骆耀祖.Linux网络服务器管理教程[M].电子工业出版社.2007.

[4]陈忠文.Linux操作系统实训教程[M].中国电力出版社.2006.

[5]冯昊.Linux服务器配置与管理(第2版)[M].清华大学出版社.2009.

Socket 篇8

1 开发环境和技术准备

1.1 开发及运行环境

(1) 操作系统:Windows 2000、Windows XP、Windows2003或Linux等。

(2) 开发工具:MyEclipse, JDK6.0。

(3) CPU:Pentium4 1.8GHz。

(4) 内存:128MB以上。

1.2 技术准备

1.2.1 Socket

Socket是面向客户/服务器模型而设计的, Socket接口是TCP/IP网络的API, Socket接口定义了许多函数或例程, Java程序员可以用它们来开发TCP/IP网络上的应用程序。在Java中, Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端, Socket是建立网络连接时使用的。在连接成功时, 应用程序两端都会产生一个Socket实例, 只需操作这个实例, 就可完成所需的会话。

1.2.2 多线程

多线程是这样一种机制, 它允许在程序中并发执行多个指令流, 每个指令流都称为一个线程, 彼此间互相独立。线程又称为轻量级进程, 它和进程一样拥有独立的执行控制, 由操作系统负责调度, 区别在于线程没有独立的存储空间, 而是和所属进程中的其他线程共享一个存储空间, 这使得线程间的通信远较进程简单。多个线程的执行是并发的, 也就是在逻辑上“同时”, 而不管是否是物理上的“同时”。

葛福鸿张丽萍

1.2.3 MVC设计模式

MVC (Model-View-Controller, 即模型层-视图层-控制层是一种设计模式, 它强制地将应用程序的输入、处理以及输出分开。MVC模型3个核心部分:模型层、视图层和控制层, 分别负担不同的任务。视图层位于用户客户端。模型层和控制层位于服务器端。

2 功能设计

2.1 客户端功能

(1) 登录上线。

(2) 显示其他在线用户。

(3) 更新自己的在线用户列表。

(4) 与其他上线用户发起会话 (一对一私聊) 。

(5) 与多名上线用户群聊。

(6) 发送和接收文件。

2.2 服务器端功能

(1) 记录上线用户的信息, 将其发送给其他在线用户。

(2) 接收用户下线信息, 将其发送给其他在线用户。

(3) 接收用户群聊信息, 将其发送给所有在线用户。

(4) 接收用户私聊信息, 将其发送给相应的在线用户。

(5) 接收用户文件信息, 将其发送给相应的在线用户。

2.3 功能结构

系统功能结构如图1所示。

3 总体框架

3.1 文件架构

(1) Client.java文件:客户端主程序源文件。

(2) Clientframe.java文件:客户端用户界面实现源文件。

(3) ClientUtil.java文件:处理字符串和显示信息工具类源文件。

(4) Server.java文件:服务器端源文件。

(5) Message.java文件:定义了聊天信息和文件信息。

(6) Usermessage.java文件:定义了用户信息。

(7) Image文件夹:存放程序中使用按钮图片和表情图片, 打jar包时一并打入。

3.2 系统架构

3.2.1 系统类

(1) Client类:实现客户端的功能。

(2) Clientframe类:设计客户端的用户界面。

(3) ClientUtil类:用于处理字符串和显示信息和表情图片的工具类。

(4) Server类:服务器端主类, 用于实现服务器端功能。

(5) Message类:实现了聊天信息的属性和方法。

(6) Usermessage类:实现了用户信息的属性和方法。

3.2.2系统类关系视图

系统类关系视图如图2所示。

3.2.3 系统实现关键

(1) 控制好Socket个数和分配是决定程序能否完成的关键。

(2) 实现群聊是整个程序关键, 利用群聊可以实现单聊和文件传送。

(3) 理清服务器端和客户端交互过程和传递的数据。

如何理解整个客户端和服务器端通信的这个模型, 主要是对ServerSocket中的accept方法接收到的Socket的理解。通信过程是:首先服务器端启动, 建立监听端口, 等待连接。其次是客户端 (C1、C2和C3) 与服务器发起连接, 由ServerSocket中的accept方法建立一个Socket (S1、S2和S3) , 客户端和服务器双方就分别通过各自相对应的Socket进行通信, 而ServerSocket建立的监听端口则继续进行监听, 它本身并不参与具体的通信过程。

4 主要功能模块设计和实现

4.1 用户列表模块

4.1.1 用户列表界面

当用户输入用户名后就会进入到用户列表窗口, 界面设计如图3所示。

4.1.2用户列表功能实现

用户列表窗口要完成的功能是:显示所有在线用户信息、监听群聊事件和监听私聊事件, 并触发聊天窗口的显示。

显示所有在线用户信息的代码如下:

4.2 用户通信模块

4.2.1 聊天界面

当用户点击群聊按钮或双击用户列表中某个在线用户后就会弹出到聊天窗口, 界面设计如图4所示。

4.2.2 聊天功能实现

私聊和群聊使用同一处理模块, 该模块处理已接收信息, 将表情与字符分开, 主要代码如下:

将处理过的信息显示在面板上:

4.3 服务器转发模块

服务器端不需要出现图形用户界面, 服务器端所要做的工作就是接收各个客户端传来的信息, 识别信息的类型 (包括用户信息、上线信息、私聊信息、群聊信息和文件信息) , 再将信息转发给相应的客户。

将监听方法做成一个线程, 此线程只负责监听, 用于产生一个新的Socket, 并将其存储起来, 关键代码如下:

转发聊天信息:

整个系统全部用Java技术来实现, 能够实现平台无关性、可移植性等。Java技术在网络编程方面具有很多优点, 但由于其自身的机制, 仍有许多有待改善的地方, 比如运行速度慢等。只有对Java进行改进, 才能是其得到更广泛的应用。

参考文献

[1]陈更力, 张青.基于Java Socket网络编程的一种新实现[J].电脑开发与用, 2006 (6) :13.

[2]袁海燕, 王文涛.Java实用程序设计100例[M].北京:人民邮电出社, 2005:226-229.13.

[3]陈小平.Java在Client/Server网络中的应用.安徽工业大学学报[N], 2002.

[4]Merlin Hughes, 等, 著, 刘先勇, 等, 译.Java网络编程技术内幕[M].国防工业出版社, 2002.

Socket 篇9

1 Socket基本原理

在C#中, MS为我们提供了System.Net.Sockets命名空间, 程序员可以通过socket来发送和接收网络上的数据。我们可以把它理解成是一个API, 有了它就可以通过这个接口访问网络从而省去了很多复杂的操作。

要通过互联网进行通信, 至少需要一对套接字, 它是通信主机之间的端点, 由它构成了单个主机内及整个网络间的编程界面。我们把运行于客户机端的称之Client Socket, 运行于服务器端的称之为Server Socket。它的连接过程可以分为三个步骤:服务器监听, 客户端请求, 连接确认。

2 Socket通信过程的实现

2.1 服务器端

申请一个Socket, 定义到一个IP地址和一个端口上开启侦听。每成功接受一个客户端的链接便在服务端产生一个对应的Socket, 在接收客户端连接时创建责和对应的客户端通信。

int recv;//用于表示客户端发送的信息长度

byte[]data=new byte[1024];//用于缓存客户端所发送的信息

IPEnd Point ipep=new IPEnd Point (IPAddress.Any, 9050) ;//定义一网络端点Socket newsock=newSocket (Address Family.Inter Network, Socket Type.Dgram, Protocol Type.Udp) ;//定义一个Socket

newsock.Bind (ipep) ;//Socket与本地的一个终结点相关联

IPEnd Point sender=new IPEnd Point (IPAddress.Any, 0) ;//定义要发送的计算机的地址

recv=newsock.Receive From (data, ref Remote) ;//接受数据

newsock.Send To (data, data.Length, Socket Flags.None, Remote) ;//发送信息

2.2 客户端

申请一个Socket, 连接服务器 (必须指明IP地址和端口号) , 通过创建一个Socket对象来初始化一个服务器端的TCP链接:

byte[]data=new byte[1024];//定义一个数组用来做数据的缓冲区

string input, string Data;

IPEnd Point ipep=new IPEnd Point (IPAddress.Parse ("1 2 7.0.0.1") , 9050) ;

//本机预使用的IP和端口

server.Send To (data, data.Length, Socket Flags.None, ipep) ;//将数据发送到指定的终结点

data=new byte[1024];

int recv=server.Receive From (data, ref Remote) ;//接受来自服务器的数据

2.3 服务器

服务器接到连接请求后, 产生一个新的Socket (端口大于1024) 与客户端建立连接并进行通讯, 原侦听Socket继续侦听。每个服务打开一个socket, 并绑定到一个端口上, 不同的端口对应不同的服务 (应用程序) 。

3 结语

许多Internet服务都可以见到Socket的踪影, 如Telnet、Http、Email、Echo等, 这些服务尽管通讯协议Protocol的定义不同, 但是其基础的传输都是采用的Socket。针对Socket编程, .NET框架的Socket类是Winsock32 API提供的套接字服务的托管代码版本。其中为实现网络编程提供了大量的方法, 大多数情况下, Socket类方法只是将数据封送到它们的本机Win32副本中并处理, 如果你熟悉Winsock API函数, 那么用Socket类编写网络程序会非常容易。

摘要:本文简要介绍了c#中Socket的通信流程, 探讨了基于多线程和Scoket在不同的程序之间进行数据通信的方法, 并通过实例讲解了多线程Socket通信的实现过程。

关键词:多线程,Scoket,通信

参考文献

[1]郑阿奇.Visual C#网络编程[M].电子工业出版社, 2011 (10) .

[2]马骏.C#网络应用编程[M].人民邮电出版社, 2010 (2) .

Socket 篇10

大部分网络协议的实现都由客户端 (Client) 和服务器端 (Server) 来协作完成。这种模型本质上涉及两个不同的程序, 通常这两个程序在不同机器上运行。这些机器之间都有网络连接。服务器端程序提供服务并对来自客户程序的请求作成响应。而客户端程序则是在使用者和服务器端程序之间建立某种沟通的渠道, 或者是作为使用服务器端提供的某种网络服务的工具。

一个典型的服务器与客户机之间的交互可能如下所示:

(1) 客户机提出一个请求;

(2) 服务器收到客户机的请求, 进行分析处理;

(3) 服务器将运行处理的结果返回给客户机。

通常一个服务器需要向多个客户机提供服务。因此对服务器来说, 还需要考虑如何有效地处理多个客户的请求。

2 服务器与客户端的Socket通信类型

Socket的连接类型可以分为两种, 分别是面向连接的字节流类型 (Sock_stream) 和面向无连接数据报类型 (Sock_dgram) 。

面向无连接数据报类型的Socket工作流程比较简单, 双方不需要进行太多的沟通与交互。客户机直接将用户的请求打包发送到服务器端, 省略了建立一个固定信息通道的过程。服务器端也是直接将处理的结果发送给客户端。其工作流程如图1所示。

面向连接的字节流类型的Socket工作中有比较严格的操作次序, 工作的原理也比较复杂。在这种类型的Socket的工作过程中, 必须首先启动服务器端, 通过调用Socket () 函数建立一个Socket对象, 然后调用Bind () 函数将该Socket对象和本地网络地址绑定到一起, 再调用Listen () 函数使该Socket对象处于侦听状态, 并规定它的最大请求的数量。其工作流程如图2所示。

总的来说, 无连接和面向连接的通信方式各有长处和短处。在仅仅涉及少量的信息传递的场合可以使用无连接操作;如果涉及大量信息传递的场合可以采用面向连接操作。

3 Delphi的Socket组件

ClientSocket组件为客户端组件。它是通信的请求方, 也就是说, 它是主动地与服务器端建立连接。

ServerSocket组件为服务器端组件。它是通信的响应方, 也就是说, 它的动作是监听以及被动接受客户端的连接请求, 并对请求进行回复。

ServerSocket组件可以同时接受一个或多个ClientSocket组件的连接请求, 并与每个ClientSocket组件建立单独的连接, 进行单独的通信。因此, 一个服务器端可以为多个客户端服务。

(1) ServerSocket的属性

Port是通信的端口, 必须设置。在本文实例中设置为95;

ServerType服务器端读写信息类型, 设置为st ThreadBlocking表示异步读写信息, 本文实例中采用这种方式。

ThreadCacheSize, 客户端的最大连接数, 就是服务器端最多允许多少客户端同时连接。本文实例采用默认值10。

其他属性采用默认设置即可。

(2) ClientSocket的属性

Port, 是通信的端口, 必须与服务器端的设置相同。否则可能导致两个组件发送的目标端口和接收的端口不一致, 导致无法建立有效的信息传送连接。

ClientType, 客户端读写信息类型, 应该与服务器端的设置相同, 为ctNonBlocking表示异步读写信息.

Host, 客户端要连接的服务器的ip地址。必须设置, 当然也可以在代码中动态设置。

其他属性采用默认设置即可。

4 应用实例

4.1 设计思路

实例包括一个服务器端程序与一个客户端程序。客户端程序可以放到多个计算机上运行, 同时与服务器端进行连接通信。

(1) 服务器程序实现以下基本功能

1) 在用户登录的时候记录用户登录所在主机的IP、主机名称等。

2) 显示当前在线用户数量。

3) 可对当前在线用户执行注销、重启、关机等操作。

(2) 客户端程序实现一些基本功能

1) 显示当前程序的工作状况。

2) 实现服务器端发送的注销、重启、关机的操作。

4.2 程序说明

根据功能的实际需要, 服务端程序一运行, 窗体的String Grid控件就显示已在线用户的基本信息, 如图3所示。

代码如下:

在窗体上, “执行”按钮的Click事件负责向指定的在线用户或全体在线用户发送注销、重启、关机操作指令。代码如下:

客户端程序通过通信端口接收指令, 并作出响应, 弹出关机提示对话框, 如需要继续使用计算机的在线用户, 可点击“取消”按钮, 如图4、图5所示。

代码如下:

并在客户端程序通信失败、通信成功、通信断开等状态, 作出响应的处理, 代码如下:

5 结语

综上所述, Socket组件相比其他高级协议组件如Fast Net组件, 它的封装层次较低, 程序员可以在它们的基础上自己定义新的高级协议或者是规定自己的信息交互流程。利用以上代码, 进一步拓展的余地也很大, 还可以加入一些更细化的功能, 如关闭与指定的在线用户的连接、可以让在线用户自己设置指令的执行时间等。

摘要:介绍有关Socket通讯应用的基本知识, 并通过客户端和服务器端的Delphi编程实例, 说明两者是如何进行通信的。

关键词:Socket,Delphi,通信,客户端,服务器端

参考文献

[1]赵秀英.Delphi网络高级编程.人民邮电出版社, 2001.

上一篇:甲烷含量下一篇:盘点肿瘤防治新进展

本站热搜

    相关推荐