欢迎来到皮皮网网首页

【innodb 锁实现 源码】【小店直播源码】【源码成了硬伤】tcp socket 源码

来源:传奇钓鱼源码 时间:2024-11-15 06:05:28

1.tcp socket Դ??
2.求一份unity中Socket-TCP从服务器接收数据方法的代码
3.一文搞懂Linux的Socket编程原理(含实例解析)
4.一文从linux源码看socket的close基本概括
5.死磕NIO— 探索 SocketChannel 的核心原理
6.程序问题。这是个TCP服务器的程序,一直输出Failed socket()不知道是怎么回事。

tcp socket 源码

tcp socket Դ??

       关闭socket.Close()后,socket对象就为null,再次打开socket时会发生异常。innodb 锁实现 源码稍微修改一下:

private void tcpStart_Click(object sender, EventArgs e)      

       {

           //IPAddress ipAddr = IPAddress.Parse("...");

           IPAddress ipAddr = IPAddress.Parse(IP);

           IPEndPoint ipEnd = new IPEndPoint(ipAddr, );

           //创建socket实例!加上这句!!!!! 

           socket = new Socket(AddressFamily.InterNetwork, 

                   SocketType.Stream, 

                   ProtocolType.Tcp)     

           try

           {

               socket.Connect(ipEnd);

               btnStart.Enabled = true;

               MessageBox.Show("TCP连接成功!!");

           }

           catch

           {

               MessageBox.Show("TCP连接失败!!");

           }

       }

求一份unity中Socket-TCP从服务器接收数据方法的代码

       接收的字节使用了protubuf反序列化,处理的时候要注意和服务器发送消息类型、大小定义一致。如果不需要可以直接删除,用服务器发送字符串也是一样

       using System.Collections;

       using System.Collections.Generic;

       using UnityEngine;

       using System.Net.Sockets;

       using System;

       using UnityEngine.Networking;

       using System.Text;

       using Google.Protobuf;

       using Pb;

       using System.Net;

       using System.IO;

       namespace Net

       {

       public class SocketClient

       {

       #region Public Variables

       public static SocketClient Instance { get; private set; }

       [Header("Network")]

       public string ipAdress = ".0.0.1";

       public int port = ;

       public float waitingMessagesFrequency = 1;

       public bool loggedIn { get; private set; }

       public bool FullLog = true;

       #endregion

       #region Private m_Variables

       private TcpClient m_Client;

       private NetworkStream m_NetStream = null;

       private byte[] m_Buffer = new byte[];

       private NetworkStream m_OutStream;

       [Tooltip("This value should be >= to Server waitingMessagesFrequency")]

       [Min(0)] private float m_DelayedCloseTime = 0.5f;

       #endregion

       #region Delegate Variables

       protected Action OnClientStarted = null; //Delegate triggered when client start

       protected Action OnClientClosed = null; //Delegate triggered when client close

       #endregion

       private void Awake()

       {

       if (Instance == null)

       Instance = this;

       }

       //Start client and stablish connection with server

       public void StartClient()

       {

       //Early out

       if (m_Client != null)

       {

       ClientLogError($"There is already a runing client on { ipAdress}::{ port}");

       return;

       }

       try

       {

       //Create new client

       m_Client = new TcpClient();

       //Set and enable client

       m_Client.BeginConnect(ipAdress, port, new AsyncCallback(OnConnect), null);

       ClientLogInfo($"Client Started on { ipAdress}::{ port}");

       OnClientStarted?.Invoke();

       }

       catch (SocketException)

       {

       ClientLogError("Socket Exception: Start Server first");

       OnClose();

       }

       }

       private void OnConnect(IAsyncResult asr)

       {

       ClientLogInfo("Connect Sucessful.");

       m_NetStream = m_Client.GetStream();

       m_Client.GetStream().BeginRead(m_Buffer, 0, m_Buffer.Length, new AsyncCallback(OnRead), m_Client);

       }

       #region Receive Message

       private void OnRead(IAsyncResult result)

       {

       OnReceivedMessage(m_Buffer);

       NetworkStream stream = m_Client.GetStream();

       lock (stream)

       {

       Array.Clear(m_Buffer, 0, m_Buffer.Length);

       m_Client.GetStream().BeginRead(m_Buffer, 0, m_Buffer.Length, new AsyncCallback(OnRead), m_Client);

       }

       }

       private void OnReceivedMessage(byte[] bytes)

       {

       ByteBuffer buffer = new ByteBuffer(bytes);

       OnRecieveMessageDeal(buffer, 0);

       }

       private void OnRecieveMessageDeal(ByteBuffer buffer, ushort length = 0)

       {

       // 判断传参length是否为0,如果不为0则代表非首次调用,不再取length值而使用传递的length

       ushort nextLength;

       if(length != 0)

       {

       nextLength = length;

       }

       else

       { // 判断传参length是否为0,如果为0则为首次调用,直接取出length后进行处理

       nextLength = buffer.ReadUInt();

       }

       uint pId = buffer.ReadUInt();

       ClientLogInfo("Length:" + nextLength + ".id:" + pId);

       byte[] bytes = buffer.ReadBytes(nextLength);

       NetLogic(pId, bytes);

       // 取出下一个length,如果为0则没有数据了,不为0则递归调用,并且传递已经取出的小店直播源码长度值

       nextLength = buffer.ReadUInt();

       if (nextLength != 0)

       {

       OnRecieveMessageDeal(buffer, nextLength);

       }

       }

       #endregion

       #region Process

       private void NetLogic(uint pid, byte[] bytes)

       {

       ClientLogInfo("Get Msg Id :" + pid);

       if (pid == 1)

       {

       SyncPid syncPid = SyncPid.Parser.ParseFrom(bytes);

       ClientLogInfo("sync pid:"+syncPid.Pid);

       }

       if (pid == )

       {

       BroadCast broadCast = BroadCast.Parser.ParseFrom(bytes);

       ClientLogInfo("broadCast-pid:" + broadCast.Pid);

       ClientLogInfo("broadCast-Tp:" + broadCast.Tp);

       ClientLogInfo("broadCast-Position-x:" + broadCast.P.X);

       ClientLogInfo("broadCast-Position-y:" + broadCast.P.Y);

       ClientLogInfo("broadCast-Position-z:" + broadCast.P.Z);

       ClientLogInfo("broadCast-Position-v:" + broadCast.P.V);

       }

       }

       #endregion

       #region Send Message

       private void WriteMessage(byte[] message)

       {

       MemoryStream memoryStream2;

       MemoryStream memoryStream = memoryStream2 = new MemoryStream();

       try

       {

       memoryStream.Position = 0L;

       BinaryWriter binaryWriter = new BinaryWriter(memoryStream);

       ushort num = (ushort)message.Length;

       binaryWriter.Write(message);

       binaryWriter.Flush();

       if (m_Client != null && this.m_Client.Connected)

       {

       byte[] array = memoryStream.ToArray();

       m_OutStream.BeginWrite(array, 0, array.Length, new AsyncCallback(OnWrite), null);

       }

       else

       {

       ClientLogError("client.connected----->>false");

       }

       }

       finally

       {

       if (memoryStream2 != null)

       {

       ((IDisposable)memoryStream2).Dispose();

       }

       }

       }

       private void OnWrite(IAsyncResult r)

       {

       try

       {

       m_OutStream.EndWrite(r);

       }

       catch (Exception ex)

       {

       ClientLogError("OnWrite--->>>" + ex.Message);

       }

       }

       public void SendMessage(ByteBuffer buffer)

       {

       this.SessionSend(buffer.ToBytes());

       buffer.Close();

       }

       private void SessionSend(byte[] bytes)

       {

       this.WriteMessage(bytes);

       }

       #endregion

       #region Close Client

       //Close client connection

       public void Close()

       {

       if (m_Client != null)

       {

       if (m_Client.Connected)

       {

       m_Client.Close();

       }

       m_Client = null;

       }

       loggedIn = false;

       }

       public void OnClose()

       {

       ClientLogError("Client Closed");

       //Reset everything to defaults

       if (m_Client.Connected)

       m_Client.Close();

       if (m_Client != null)

       m_Client = null;

       OnClientClosed?.Invoke();

       }

       #endregion

       #region ClientLog

       // Custom Client Log With Text Color

       public void ClientLogInfo(string msg)

       {

       if (FullLog)

       {

       Debug.Log($"<color=green>Client:</color>{ msg}");

       }

       }

       public void ClientLogWarning(string msg)

       {

       if (FullLog)

       {

       Debug.LogWarning($"<color=yellow>Client:</color>{ msg}");

       }

       }

       public void ClientLogError(string msg)

       {

       if (FullLog)

       {

       Debug.LogError($"<color=red>Client:</color>{ msg}");

       }

       }

       //Custom Client Log Without Text Color

       public void ClientLog(string msg)

       {

       if (FullLog)

       {

       Debug.Log($"Client:{ msg}");

       }

       }

       #endregion

       }

       }

一文搞懂Linux的Socket编程原理(含实例解析)

       掌握Linux Socket编程:从原理到实战示例

       在单机系统中,进程间通信并非难题,操作系统提供了管道、命名管道和信号等多种手段。然而,当涉及网络通信,我们需要解决进程标识和协议识别的问题。Linux的世界里,TCP/IP协议族中的套接字(Socket)扮演了核心角色,"一切皆Socket",它简化了与网络的交互。

       TCP/IP,工业标准协议集,不仅支持Berkeley套接字,还有其快速的UDP协议,作为TCP/IP协议族的重要成员。Socket设计精巧,作为抽象层,它提供统一的接口,如socket套接字(如同文件操作)和套接字描述符(一个整数标识符),使得开发者可以轻松处理网络通信。

       标准错误输出与Socket紧密相连,0、1、2分别对应stdin、stdout和stderr,而socket API巧妙地将这些整合进UNIX系统,创建套接字后,源码成了硬伤返回的描述符成为操作网络的核心工具。

       描述符是操作系统为进程管理的文件结构索引,无论是文件还是套接字I/O,通过描述符进行操作,显得直观且高效。创建socket时,只需调用socket()函数,随后的通信操作则依赖于填充的套接字属性。

       服务器端的通信流程有序且逻辑清晰:初始化Socket,通过bind()指定监听地址和端口,接着listen()等待连接,accept()接收并处理客户端的连接请求,交互结束后,通过close()关闭连接。理解这些步骤至关重要。

       在创建Socket时,我们通过socket()函数生成套接字描述符,同时可以选择不同的协议族(AF_INET, AF_INET6, AF_LOCAL等)和套接字类型(如SOCK_STREAM和SOCK_DGRAM),这些组合确保了通信的准确性和兼容性。bind()函数则绑定socket到一个特定的地址,服务器通常在listen前绑定熟知地址。

       理解大端和小端模式对于正确处理网络字节序至关重要。在进行套接字操作时,务必确保数据按网络字节序发送,以避免潜在的混乱。三次握手(客户端SYN、服务器SYN+ACK、dataease源码部署客户端ACK)在连接建立中起着关键作用,而listen()和connect()则是这些过程的调用者。

       服务器通过accept()接收连接请求,区分监听套接字与连接套接字,这对于理解服务器和客户端的角色至关重要。在实际操作中,如使用recvmsg/sendmsg进行网络I/O,读写操作需要特别处理异常情况,如中断或连接断开。

       最后,TCP连接的建立和关闭遵循严格的四次挥手协议:三次握手建立连接,四次挥手确保数据传输完成。在服务器端,一个示例程序可能包括监听特定端口、接受连接请求并交互数据,同时处理可能的TIME_WAIT状态,确保数据传输的完整性和可靠性。

       无论是客户端还是服务器,Socket编程的实践都需要掌握这些核心概念。通过实际操作和案例分析,一步步揭开Socket编程的神秘面纱,你将能够自如地在Linux世界中进行高效的进程间通信。

一文从linux源码看socket的close基本概括

       理解TCP关闭过程的关键在于四次挥手,这个过程是主动关闭、被动关闭和同时关闭的统一体现。在主动关闭close(fd)的过程中,通过C语言中的OTC商家源码close(int fd)函数调用系统调用sys_close,进而执行filp_close方法。随后,fput函数处理多进程中的socket引用问题,确保父进程也正确关闭socket。在f_op->release的实现中,我们关注socket与file的关系以及close(fd)调用链。随着状态机的变迁,TCP从FIN_WAIT1变迁至FIN_WAIT2,设置一个TCP_FIN_WAIT2定时器,防止由于对端未回应导致的长时间等待。FIN_WAIT2状态等待对端的FIN,完成最后两次挥手。接收对端FIN后,状态变化至time_wait,原socket资源被回收,并在时间等待超时后从系统中清除。在被动关闭中,接收FIN进入close_wait状态,应用关闭连接时改变状态为last_ack,并发送本端的FIN。被动关闭的后两次挥手后,连接关闭。出现大量close_wait通常与应用检测到对端FIN时未及时关闭有关,解决方法包括调整连接池的参数或加入心跳检测。操作系统通过包活定时器在超时后强制关闭连接。进程退出时会关闭所有文件描述符,再次触发filp_close函数。在Java中,通过重写finalize方法,GC会在释放内存时关闭未被引用的socket,但不可完全依赖GC来管理socket资源,以避免潜在的内存泄露问题。总结,深入理解TCP关闭过程有助于优化网络应用程序的性能和稳定性,同时阅读Linux内核源代码需要耐心和系统性的方法。

死磕NIO— 探索 SocketChannel 的核心原理

       深入探索 SocketChannel 的核心原理,首先,我们需要了解 Socket 的基本概念。Socket 是计算机网络中用于进程间通信的抽象层,它结合了 IP 地址、协议和端口信息,以实现应用程序间的通信。TCP/IP 协议族通过三元组(IP地址、协议、端口)来指明数据应发送至哪个应用程序,而 Socket API(如 UNIX BSD 的套接字(socket))允许应用程序实现网络通信。

       在 TCP/IP 四层模型中,Socket 作为一种抽象接口,连接了应用层与传输层,使得应用层无需直接关注复杂的 TCP/IP 协议细节。SocketChannel 是针对 TCP 网络Socket 的一种通道改进,支持非阻塞的读写操作。它具有以下特点:创建、校验连接、读取数据、写入数据、设置 I/O 模式和关闭通道。

       使用 SocketChannel 涉及创建通道、校验连接状态、读取和写入数据等操作。创建 SocketChannel 通常通过 open() 方法实现,而连接服务器则通过 connect() 方法。读取数据时,SocketChannel 会使用 read() 方法将数据读入到 ByteBuffer 中;写入数据则使用 write() 方法。此外,SocketChannel 支持阻塞和非阻塞两种 I/O 模式,可通过 configureBlocking() 方法进行切换。当完成通信后,应通过 close() 方法关闭 SocketChannel 实例。

       深入 SocketChannel 的源码,可以看到其核心子类 SocketChannel 实现了大部分功能。创建 SocketChannel 实例时,通过 SelectorProvider 创建并调用 openSocketChannel() 方法。SocketChannelImpl 作为 SocketChannel 的实现类,在构造函数中实例化 SocketChannel 对象。文件描述符(fd)用于与操作系统进行文件或网络连接的交互,状态变量指示通道当前的连接状态。连接服务器、读取和写入数据等核心操作通过调用相关方法实现,这些操作在底层通常会与系统调用或 native 方法交互。

       了解 SocketChannel 的工作原理和使用方法对于构建高效、可靠的网络应用程序至关重要。深入研究 SocketChannel 的实现细节,能够帮助开发者更好地利用其非阻塞特性,优化网络通信性能。在完成 SocketChannel 相关内容后,接下来的文章将开始探索第三个组件:Selector,以进一步深入了解 Java 网络编程的高级功能。

程序问题。这是个TCP服务器的程序,一直输出Failed socket()不知道是怎么回事。

       主函数内创建套接字socket函数调用之前,要加个WSAStartup函数。因为默认网络对应的DLL文件是不会自动加载到应用程序上的,必须使用WSAStartup做初始化。

       形式如下:

        // 初始化 Winsock.

        WSADATA wsaData;

        int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );

        if ( iResult != NO_ERROR )

        {

        printf("Error at WSAStartup()\n");

        }

从Linux源码看Socket(TCP)的listen及连接队列

       了解Linux内核中Socket (TCP)的"listen"及连接队列机制是深入理解网络编程的关键。本文将基于Linux 3.内核版本,从源码角度解析Server端Socket在进行"listen"时的具体实现。

       建立Server端Socket需要经历socket、bind、listen、accept四个步骤。本文聚焦于"listen"步骤,深入探讨其内部机理。

       通过socket系统调用,我们可以创建一个基于TCP的Socket。这里直接展示了与TCP Socket相关联的操作函数。

       接着,我们深入到"listen"系统调用。注意,glibc的INLINE_SYSCALL对返回值进行了封装,仅保留0和-1两种结果,并将错误码的绝对值记录在errno中。其中,backlog参数至关重要,设置不当会引入隐蔽的陷阱。对于Java开发者而言,框架默认backlog值较小(默认),这可能导致微妙的行为差异。

       进入内核源码栈,我们发现内核对backlog值进行了调整,限制其不超过内核参数设置的somaxconn值。

       核心调用程序为inet_listen。其中,除了fastopen外的逻辑(fastopen将在单独章节深入讨论)最终调用inet_csk_listen_start,将sock链入全局的listen hash表,实现对SYN包的高效处理。

       值得注意的是,SO_REUSEPORT特性允许不同Socket监听同一端口,实现内核级的负载均衡。Nginx 1.9.1版本启用此功能后,性能提升3倍。

       半连接队列与全连接队列是连接处理中的关键组件。通常提及的sync_queue与accept_queue并非全貌,sync_queue实际上是syn_table,而全连接队列为icsk_accept_queue。在三次握手过程中,这两个队列分别承担着不同角色。

       在连接处理中,除了qlen与sk_ack_backlog计数器外,qlen_young计数器用于特定场景下的统计。SYN_ACK的重传定时器在内核中以ms为间隔运行,确保连接建立过程的稳定。

       半连接队列的存在是为抵御半连接攻击,避免消耗大量内存资源。通过syn_cookie机制,内核能有效防御此类攻击。

       全连接队列的最大长度受到限制,超过somaxconn值的连接会被内核丢弃。若未启用tcp_abort_on_overflow特性,客户端可能在调用时才会察觉到连接被丢弃。启用此特性或增大backlog值是应对这一问题的策略。

       backlog参数对半连接队列容量产生影响,导致内核发送cookie校验时出现常见的内存溢出警告。

       总结而言,TCP协议在数十年的演进中变得复杂,深入阅读源码成为分析问题的重要途径。本文深入解析了Linux内核中Socket (TCP)的"listen"及连接队列机制,旨在帮助开发者更深入地理解网络编程。