c#socket怎样让服务器端转发数据QQA,B(a发送数据到服务端,服务端立即转发到b)

c#socket怎样让服务器端转发数据QQA,B(a发送数据到服务端,服务端立即转发到b),第1张

这个类似于聊天室的信息转发,建议建立一个数据结构,如

[SerializableAttribute]

[ComVisibleAttribute(true)]

public class SendType

{

public string SendName {getset}

public string RecName {getset}

public string Data {getset}

}

新建一个结构变量,public SendType SendData = new SendType()

SendData.SendName = "A"

SendData.RecName = "B"

SendData.Data = "Hello"

如此初始化后,将变量序列化后,提取byte[]数组直接发送,服务器再接收后再反序列化,转发。

[SerializableAttribute]

[ComVisibleAttribute(true)]

两个标记就是标记SendType类为可序列化,否则会造成不能序列化的编译错误。

public class TCPlient {

public static void main(String[] args) {

String str = null

Socket clientSocket// 创建客户端套接

DataInputStream in = null// 创建DataInputStream对象

DataOutputStream out = null// 创建DataOutputStream对象

try {

clientSocket = new Socket("127.0.0.1", 4331)// 实例化Socket对象

//clientSocket = new Socket("192.168.152.139", 6379)

in = new DataInputStream(clientSocket.getInputStream())// 实例化DataInputStream对象

// 实例化DataOutputStream对象

out = new DataOutputStream(clientSocket.getOutputStream())

out.writeUTF("你好!!")// 写数据

while (true) {

str = in.readUTF()// 读取流中数据

out.writeUTF(((int) (Math.random() * 10) + 1) + "")// 向流中写入0到10之间的随机数

System.out.println("客户端收到:" + str)// 输出信息

Thread.sleep(1000)// 线程休眠

}

} catch (Exception e) {

e.printStackTrace()

}

}

}

public class TCPServer {

public static void main(String[] args) {

ServerSocket serverSocket = null// 创建服务器端套接字

Socket clientSocket = null// 创建客户端套接字

String str = null

DataOutputStream out = null// 创建DataOutputStream类对象

DataInputStream in = null// 创建DataInputStream类对象

try {

serverSocket = new ServerSocket(4331)// 实例化ServerSocket对象

clientSocket = serverSocket.accept()// 接收客户的套接字连接呼叫

in = new DataInputStream(clientSocket.getInputStream())// 实例化DataInputStream对象

out = new DataOutputStream(clientSocket.getOutputStream())// 实例化DataOutputStream对象

while (true) {

str = in.readUTF()// 读取客户放入连接中的信息

out.writeUTF("hello,我是服务器")// 通过输出流向线路中写信息

out.writeUTF(str)

System.out.println("服务器收到:" + str)

Thread.sleep(1000)// 线程休眠

}

} catch (Exception e) {

e.printStackTrace()

}

}

}

//要发到另一个client,就让server转发消息就行。

在正篇开始之前,我先提问几个问题,不知道你是否全都了解:

(1) 网络请求是通过http发送的吗?

(2) http与tcp之间的关系?

(3) 网络请求是怎么发送的,通过什么形式去发送的?

在过往对于http与tcp的理解其实只是一个简单模糊的概念,仔细想想其实http只是一种协议,tcp只是用于建立一个持久连接,它们都不是用于网络发送数据的根本,真正发送数据的是我们的物理层,http协议只是作为一个标识的作用,简单来说是定位到某一主机。

下面来介绍一下计算机网络体系结构

计算机网络分为7层,分别是物理层,数据链路层,网络层,传输层,会话层,表示层以及应用层,由于7层太多所以后面经过演变之后定为5层,把应用层,会话层,表示层给合统称为应用层,我们客户端的每一步操作,举个例子,当我们点击发送按钮请求网络的时候,这时候会通过应用层逐渐往下传递直到物理层,物理层会提供一个互联网网络接口,这时候才真正通过互联网开始传输数据,这里最主要介绍的是传输层以及物理层,其它的百度一下,传输层是第一个端到端的层次,也是进程——进程的层次。

主要功能是实现端到端的可靠数据传输、复用与分解、连接控制、流量控制和拥塞控制(这些东西都是定义去百度一下,比如说流量控制,其实就是控制数据的发送量,你不能一次性发送很多数据,原因想一下就知道了),客户端的每一步操作都会在这5层体现出来,查下定义之后就会一目了然(比如说在我们终止会话,这时候就是由会话层管理,实体间交换数据的语法,解决格式和数据表示的差别是由表示层来完成等),在我们建立连接的时候比如说发送一个http请求(原理跟后面的socket数据传输模块是一样的),我们会先建立一个tcp连接,然后发送http请求,这时候数据会经过传输层,传输层里携带了发送数据的报文(比如ip地址,端口号之类的,数据内容),向下传递到物理层,物理层最后会提供一个互联网网络接口去发送数据,数据是以比特流的形式发送,发送到交换机上面(交换机是什么,去百度查一下,不做解释),交换机是有多个的,当我们数据非常大的时候,数据会被分解发送到多个交换机上面,传到对方客户端或者服务器的时候数据会重新整合起来,上面的是一个简单的http请求,下面来介绍一下Socket。

1.Socket的整体流程:

udp客户端:创建套接字,发送数据,接收数据,关闭套接字。

udp服务端:创建套接字,绑定地址和端口号,接收数据,发送数据,关闭套接字。

tcp客户端:创建套接字,建立连接,发送数据,接收数据,关闭套接字。

tcp服务端:创建套接字,绑定地址和端口号,设置监听,建立连接,发送数据,接收数据,关闭套接字。

这些理解起来很容易,我们客户端是要发送数据的,服务端需要接收数据,所以服务端要绑定地址和端口号,而tcp是需要三次握手的所以要有监听。

2.Socket三次握手

第一次握手,客户端发送请求给服务端(询问是否可以建立连接)。

第二次捂手,服务端回应给客户端一个确认,接受连接或者拒绝连接

第三次握手,经过确认之后,客户端回应给服务端(意思是我要开始发送数据了,下一步就开始发送了)。

理解三次握手,为什么要三次,第一次握手确认客户端可以发送请求,第二次握手确认服务端可以接收并且发送,第三部确认客户端可以接收。

3.Scoket四次挥手

第一次挥手,客户端向服务器发送断开连接请求

第二次挥手,服务端回应客户端(意思是,稍等等我数据传完(处理完的意思),在断开)

第三次挥手,服务端回应客户端断开请求(可以断开了)

第四次挥手,客户端与服务端请求断开。

tcp连接是面向连接的,数据发送可靠,udp是面向无连接的,数据发送过后就不管了,下面介绍一下tcp为什么数据可靠

具体方法如下:

差错检测:我们发送数据的时候刚刚说过是由物理层提供的互联网网络接口以比特流的形式进行发送,那么这个时候差错检测利用差错编码实现数据包传输过程中的比特差错检测,保证数据正确性

确认:接收方向发送方反馈接收状态。ACK(肯定确认);NAK(否定确认)

重传:当没有接收到反馈状态。ACK(肯定确认);NAK(否定确认)的时候,或者请求超时的时候进行重新发送

计时器:内部检测,一个定时器,当数据在一定时间没有接收到确认的时候就认为发送失败,进行重传操作。

序号:刚刚说了重传有两种情况,那么当重传是因为网络超时引起的,那么这个时候计时器进行了一次重传,然后上次超时后并没有发送失败这个时候也发送成功了,这个时候就会造成数据错乱,那么序号就起了一个作用,就是给数据进行排序,以至于不错乱。

下面来说一下tcp可靠传输协议滑动窗口协议

左边的代表的是接收的数据,中间代表的是正在处理的,右边代表的是没有处理的,在我们发送数据的时候比如56789这些数据发送,56成功了,这时候窗口就会往右移动,接收的时候呢,当我们接收比如56,接收成功了,这时候窗口往右移动,这里有一个需要注意一下,比如说当我们5没有发送成功或者说5没有接收成功,而6发送成功了,这时候窗口是不会往右移动的,它会等待5发送成功后在往右移动,浮动窗口协议里还有GBN协议和SR协议,这两个的主要区别是,GBN协议的发送窗口只能发送一个,比如上面中间准备发送的5678就只能存在5一个,但是接收窗口是可以有多个的,SR协议是可以发送窗口与接收窗口都是可以多个的。

最后总结一下http请求与socket的差异,socket是套接字,用于将报文传输到传输层,http请求在发送的时候会建立tcp连接,所以http也会分为http持久性连接和非持久性连接,至于网络传输都是要经过物理层才能传输,数据经过多个交换机进行分解,传到服务器的时候在进行整合。

网卡接收到数据根据数据头,将数据写到对应的内存,并发出中断,系统接收到中断,然后通知应用吧?

VC中客户端socket与服务器连接后,需要执行一个封状的操作

朝服务器发送一些数据(命令),然后返回结果

假设全部才字符串,类似这样的函数

CString SendCommand (CString cmd,socket sk)

要求在执行这个函数的时候能同时响应用户界面操作

也就是要用异步方式

而且这个socket已经建立好,有RecvTheard在处理

我目前是用Event实现的,很别扭:

m_hevtReadStore=CreateEvent(NULL,false,FALSE,NULL)

//m_tcp是封装的socket基本操作类


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/216760.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-06
下一篇2023-04-06

发表评论

登录后才能评论

评论列表(0条)

    保存