当前位置:首页 > socket
  • udp的socket是怎样实现数据传输

         UDP简介   UDP: User Datagram Protocol的简称, 中文名是用户数据包协议,是 OSI 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。   特点:每个数据报中都给出了完整的地址信息,因此无需要建立发送方和接收方的连接。   UDP传输数据时是有大小限制的,每个被传输的数据报必须限定在64KB之内。   UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。      udp socket实现数据传输   socket编程实现UDP数据传输基于DatagramSocket与DatagramPacketAPI实现。   [java] view plain copy   [java] view plain copyimport java.io.IOExcepTIon;   import java.net.DatagramPacket;   import java.net.DatagramSocket;   import java.net.InetAddress;   /**   * 客户端发送数据   */   public class UdpClient {   public staTIc void main(String[] args) throws IOExcepTIon {   // 1.定义服务器的地址、端口号、数据   byte[] data = “udpclient发送数据”.getBytes();   InetAddress address = InetAddress.getByName(“localhost”);   int port = 8086;   // 2.创建数据报,包含发送的数据信息   DatagramPacket packet = new DatagramPacket(data, data.length, address,port);   // 3.创建DatagramSocket对象   DatagramSocket socket = new DatagramSocket();   // 4.向服务器端发送数据报   socket.send(packet);   socket.close();   }   }   [java] view plain copyimport java.io.IOExcepTIon;   import java.net.DatagramPacket;   import java.net.DatagramSocket;   /**   *服务器接收数据   */   public class UdpServer {   public static void main(String[] args) throws IOException {   DatagramSocket socket = new DatagramSocket(8086);   byte[] data = new byte[1024];   DatagramPacket packet = new DatagramPacket(data, data.length);   socket.receive(packet);   String info = new String(data, 0, packet.getLength());   System.out.println(“udpservice接收数据是” + info);   socket.close();   }   }

    时间:2020-08-04 关键词: socket udp

  • socket是什么意思_socket编程是什么意思_socket详解

      socket是什么   从编程语言的角度,socket是一个无符号整型变量,用来标识一个通信进程。两个进程通信,总要知道这几个信息:双方的ip地址和端口号,通信所采用的协议栈。socket就是和这些东西绑定的,实现socket可以使用unix提供的接口,也可以使用wIndows提供的winSock。   socket适用场合   socket是位于传输层的网络编程了,一般用于需要自己定义应用层的协议的应用程序,如果已经有了成熟的应用层协议,比如http等,可以使用jsp.php.asp或者是.net框架开发。   socket优缺点   个人认为缺点是需要记很多函数,过程较复杂需记忆。   socket如何使用   客户端:需要先建立套接字,然后申请连接服务器,需要知道服务端的ip和端口号,而不需要指定客户端的(客户端会由os分配),连接上服务器后开始读写信息,最后关闭套接字。   服务端:建立监听套接字,绑定地址和端口号,然后开始监听,等待客户机连接,生成一个响应套接字,负责处理这个连接请求,然后读写信息,关闭响应套接字,关闭监听套接字。   socket详解   Socket是进程通讯的一种方式,即调用这个网络库的一些API函数实现分布在不同主机的相关进程之间的数据交换。   几个定义:   (1)IP地址:即依照TCP/IP协议分配给本地主机的网络地址,两个进程要通讯,任一进程首先要知道通讯对方的位置,即对方的IP。   (2)端口号:用来辨别本地通讯进程,一个本地的进程在通讯时均会占用一个端口号,不同的进程端口号不同,因此在通讯前必须要分配一个没有被访问的端口号。   (3)连接:指两个进程间的通讯链路。   (4)半相关:网络中用一个三元组可以在全局唯一标志一个进程:(协议,本地地址,本地端口号)这样一个三元组,叫做一个半相关,它指定连接的每半部分。   (4)全相关:一个完整的网间进程通信需要由两个进程组成,并且只能使用同一种高层协议。也就是说,不可能通信的一端用TCP协议,而另一端用UDP协议。因此一个完整的网间通信需要一个五元组来标识:(协议,本地地址,本地端口号,远地地址,远地端口号)这样一个五元组,叫做一个相关(associaTIon),即两个协议相同的半相关才能组合成一个合适的相关,或完全指定组成一连接。   客户/服务器模式   在TCP/IP网络应用中,通信的两个进程间相互作用的主要模式是客户/服务器(Client/Server,C/S)模式,即客户向服务器发出服务请求,服务器接收到请求后,提供相应的服务。客户/服务器模式的建立基于以下两点:   (1)首先,建立网络的起因是网络中软硬件资源、运算能力和信息不均等,需要共享,从而造就拥有众多资源的主机提供服务,资源较少的客户请求服务这一非对等作用。   (2)其次,网间进程通信完全是异步的,相互通信的进程间既不存在父子关系,又不共享内存缓冲区,因此需要一种机制为希望通信的进程间建立联系,为二者的数据交换提供同步,这就是基于客户/服务器模式的TCP/IP。   服务器端:   其过程是首先服务器方要先启动,并根据请求提供相应服务。   (1)打开一通信通道并告知本地主机,它愿意在某一公认地址上的某端口(如FTP的端口可能为21)接收客户请求;   (2)等待客户请求到达该端口;   (3)接收到客户端的服务请求时,处理该请求并发送应答信号。接收到并发服务请求,要激活一新进程来处理这个客户请求(如UNIX系统中用fork、exec)。新进程处理此客户请求,并不需要对其它请求作出应答。服务完成后,关闭此新进程与客户的通信链路,并终止。   (4)返回第(2)步,等待另一客户请求。   (5)关闭服务器   客户端:   (1)打开一通信通道,并连接到服务器所在主机的特定端口;   (2)向服务器发服务请求报文,等待并接收应答;继续提出请求。   (3)请求结束后关闭通信通道并终止。   从上面所描述过程可知:   (1)客户与服务器进程的作用是非对称的,因此代码不同。   (2)服务器进程一般是先启动的。只要系统运行,该服务进程一直存在,直到正常或强迫终止。

    时间:2020-08-03 关键词: socket

  • 基于Socket的java通信编程详解

      Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Socket。像大家熟悉的QQ、MSN都使用了Socket相关的技术。下面就让我们一起揭开Socket的神秘面纱。   Socket编程   一、网络基础知识(参考计算机网络)   关于计算机网络部分可以参考相关博客:   《TCP/IP协议栈及OSI参考模型详解》   http://wangdy.blog.51cto.com/3845563/1588379   1、两台计算机间进行通讯需要以下三个条件:   IP地址、协议、端口号   2、TCP/IP协议:   是目前世界上应用最为广泛的协议,是以TCP和IP为基础的不同层次上多个协议的集合,也成TCP/IP协议族、或TCP/IP协议栈   TCP:Transmission Control Protocol 传输控制协议   IP:Internet Protocol 互联网协议   3、TCP/IP五层模型   应用层:HTTP、FTP、SMTP、Telnet等   传输层:TCP/IP   网络层:   数据链路层:   物理层:网线、双绞线、网卡等   4、IP地址   为实现网络中不同计算机之间的通信,每台计算机都必须有一个唯一的标识---IP地址。   32位二进制   5、端口   区分一台主机的多个不同应用程序,端口号范围为0-65535,其中0-1023位为系统保留。   如:HTTP:80 FTP:21 Telnet:23   IP地址+端口号组成了所谓的Socket,Socket是网络上运行的程序之间双向通信链路的终结点,是TCP和UDP的基础   6、Socket套接字:   网络上具有唯一标识的IP地址和端口组合在一起才能构成唯一能识别的标识符套接字。   Socket原理机制:   通信的两端都有Socket   网络通信其实就是Socket间的通信   数据在两个Socket间通过IO传输   7、Java中的网络支持   针对网络通信的不同层次,Java提供了不同的API,其提供的网络功能有四大类:   InetAddress:用于标识网络上的硬件资源,主要是IP地址   URL:统一资源定位符,通过URL可以直接读取或写入网络上的数据   Sockets:使用TCP协议实现的网络通信Socket相关的类   Datagram:使用UDP协议,将数据保存在用户数据报中,通过网络进行通信。   二、InetAddress   InetAddress类用于标识网络上的硬件资源,标识互联网协议(IP)地址。   该类没有构造方法      三、URL类   1、URL(Uniform Resource Locator)统一资源定位符,表示Internet上某一资源的地址,协议名:资源名称      2、使用URL读取网页内容   通过URL对象的openStream()方法可以得到指定资源的输入流,通过流能够读取或访问网页上的资源      四、TCP编程   1、TCP协议是面向连接的、可靠的、有序的、以字节流的方式发送数据,通过三次握手方式建立连接,形成传输数据的通道,在连接中进行大量数据的传输,效率会稍低   2、Java中基于TCP协议实现网络通信的类   客户端的Socket类   服务器端的ServerSocket类      3、Socket通信的步骤   ① 创建ServerSocket和Socket   ② 打开连接到Socket的输入/输出流   ③ 按照协议对Socket进行读/写操作   ④ 关闭输入输出流、关闭Socket   4、服务器端:   ① 创建ServerSocket对象,绑定监听端口   ② 通过accept()方法监听客户端请求   ③ 连接建立后,通过输入流读取客户端发送的请求信息   ④ 通过输出流向客户端发送乡音信息   ⑤ 关闭相关资源      6、应用多线程实现服务器与多客户端之间的通信   ① 服务器端创建ServerSocket,循环调用accept()等待客户端连接   ② 客户端创建一个socket并请求和服务器端连接   ③ 服务器端接受苦读段请求,创建socket与该客户建立专线连接   ④ 建立连接的两个socket在一个单独的线程上对话   ⑤ 服务器端继续等待新的连接      五、UDP编程   UDP协议(用户数据报协议)是无连接的、不可靠的、无序的,速度快   进行数据传输时,首先将要传输的数据定义成数据报(Datagram),大小限制在64k,在数据报中指明数据索要达到的Socket(主机地址和端口号),然后再将数据报发送出去   DatagramPacket类:表示数据报包   DatagramSocket类:进行端到端通信的类   1、服务器端实现步骤   ① 创建DatagramSocket,指定端口号   ② 创建DatagramPacket   ③ 接受客户端发送的数据信息   ④ 读取数据      2、客户端实现步骤   ① 定义发送信息   ② 创建DatagramPacket,包含将要发送的信息   ③ 创建DatagramSocket   ④ 发送数据      六、注意问题:   1、多线程的优先级问题:   根据实际的经验,适当的降低优先级,否侧可能会有程序运行效率低的情况   2、是否关闭输出流和输入流:   对于同一个socket,如果关闭了输出流,则与该输出流关联的socket也会被关闭,所以一般不用关闭流,直接关闭socket即可   3、使用TCP通信传输对象,IO中序列化部分   4、socket编程传递文件,IO流部分

    时间:2020-08-03 关键词: socket

  • 浅谈Linux C Socket Api

    以前都只是在网上搜的能用的例子,对一些参数不是很清楚,这次汇总。而且网络通信还是很常用的通信手段。 UNIX 环境高级编程对Socket通信的描述是套接字网络IPC(进程间通信),可以用于计算机间通信也可用于计算机内通信,管道、消息队列、信号量以及共享内存等都是属于计算机内通信的情况。 一、 套接字Api详细介绍 1. 套接字描述符 首先会先到的是文件描述符,对Linux一切皆文件的哲学又多懂了一点儿点儿。 套接字是通信端点的抽象。与应用程序使用文件描述符一样,访问套接字需要使用套接字描述符。套接字描述符在UNIX系统是用文件描述符实现的。 #include int socket (int domain, int type, int protocal);返回值:成功返回文件(套接字)描述符,出错返回-1 参数domain(域)确定通信的特性,包括地址格式。各个域都有自己的格式表示地址,表示各个域的常数都以AF_开头,意指地址族(address family). 参数type确定套接字的类型,进一步确定通信特征。下图给出了一些类型,但在实现中可以自由增加对其他类型的支持。 参数protocol通常是0,表示按给定的域和套接字类型选择默认的协议。当对同一域和套接字类型支持多个协议时,可以使用proticol参数选择一个特定协议。在A_FINET通信域中套接字类型SOCK_STREAM的默认协议是TCP(传输控制协议);A_FINET通信域中套接字类型SOCK_DGRAM的默认协议是UDP(用户数据报协议)。 字节流(SOCK_STREAM)要求在交换数据之前,在本地套接字和远程套接字之间建 立一个逻辑联系。 Tcp:没有报文界限,提供的是字节流服务。之前写过Qt传输图片的拆包与解包,原因就是如此吧。 调用socket与调用open类型,均可获得用于输入、输出的文件描述符。不用的时候记得close关闭。 2. 寻址 如何确定一个目标通信进程? 进程的标识有两个部分:计算机的网络地址可以确定网络上与之想要通信的计算机 服务可以确定计算机上的特定进程。 2.1 字节序 在同一台计算机上进程间通信时,一般无需考虑字节序。 TCP/IP协议栈使用大端字节序。有关字节序大家可自行百度。 Linux系统是小端字节序。 2.2 地址格式 地址确定了特定通信域中的套接字端点,地址格式与特定的通信域相关。为使不同格式的地址能够被传入到套接字函数,地址被强转换成通用的地址结构sockaddr表示。 Linux中,sockaddr_in定义如下: struct sockaddr_in {sa_family_t sin_family;in_port_t sin_port;struct in_addr sin_addr;unsigned char sin_zero[8];}; 其中成员sin_zero为填充字段,必须全部置0. 所以在网上搜到的例子有使用bzero. 我目前使用的ubuntu定义如下: /* Structure describing an Internet socket address. */struct sockaddr_in { __SOCKADDR_COMMON (sin_); in_port_t sin_port; /* Port number. */ struct in_addr sin_addr; /* Internet address. */ /* Pad to size of `struct sockaddr'. */ unsigned char sin_zero[sizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE - sizeof (in_port_t) - sizeof (struct in_addr)]; }; 还有很多关于地址查询的函数,这里就不一一列举了。 3. 将套接字与地址绑定 使用bind函数将地址绑定到一个套接字上。 #include int bind(int sockfd, const struct sockaddr * addr, socklen_t len);返回值:成功返回0,出错返回-1 参数socklen_t使用sizeof来计算就好了。 对于使用地址的一些限制: 端口号不能小于1024,除非该进程具有相应的特权(即为超级用户)。可见规则总是因人而异,计算机也是如此~ 对于因特网域,如果指定IP地址为ADDR_ANY,套接字端点可以被绑定到所有的系统网络接口。 注意:linux的man命令可以查看api的详细说明,而且还有例子,也挺不错的。 4. 建立连接 1> connect 如果处理的是面向连接的网络服务(SOCK_STREAM或SOCK_SEQPACKET),在开始交换数据前,需要在请求服务的进程套接字(客户端)和提供服务的进程套接字(服务器)之间建立一个连接。使用connect. #include int connect(int sockfd, const struct sockaddr *addr, socklen_t len);返回值:成功返回0,出错返回-1 诶,这个参数好熟悉呀,和bind函数的参数一模一样呀~ 当client连接server时,由于一些原因,连接可能会失败。可以使用指数补偿的算法解决,了解一下即可。 2> listen server调用listen来宣告可以接受连接请求: #include Int listen(int sockfd, int backlog);返回值:成功返回0,出错返回-1 参数backlog提供了一个提示,用于表示该进程所要入队的连接请求数量。其值由系统决定,但上限由中SOMAXCONN指定。 一旦队列满,系统会拒绝多余的连接请求。 3> accept 一旦服务器调用了listen,套接字就能接收连接请求。使用函数accept获得连接请求并建立连接。 #include Int accept(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict len);返回值:成功返回文件(套接字)描述符,出错返回-1 函数accept所返回的文件描述符是套接字描述符,该描述符连接到调用connect的客户端。这个新的套接字描述符和原始套接字(sockfd)具有相同的套接字类型和地址族。传给accept的原始套接字没有关联到这个连接,而是继续保持可用状态并接受其他连接请求。 如果不关心客户端标识,可以将addr和len设置为NULL,否则addr存放的是连接的客户端的地址。 如果没有连接请求等待处理,accept会阻塞直到有请求到来。另外server可以使用poll或select来等待一个请求的到来。 5. 数据传输 既然将套接字端点表示为文件描述符,那么只要建立连接,就可以使用read和write来通过套接字通信。read和write函数我几乎不用,了解一下即可。 1> send #include Int send(int sockfd, const void *buf, size_t nbytes, int flags);返回值:成功返回发送的字节数,出错返回-1 注意:如果send成功返回,并不一定并表示连接的另一端的进程接收数据。可以保证的是数据已经无误的发送到网络上。 标志我一直用的是0 2> recv #include int recv(int sockfd, const void *buf, size_t nbytes, int flags);返回值:以字节计数的消息长度,若无可用消息或对方已经按序结束则返回0, 出错返回-1 仍然一直是0 如果想定位发送者,可以使用recvfrom来得到数据发送者的源地址。 3> recvfrom #include int recv(int sockfd, void *restrict buf, size_t len, int flag, struct sockaddr *restrict addr, socklen_t *restrict len);返回值:以字节计数的消息长度,若无可用消息或对方已经按序结束则返回0, 出错返回-1 因为可以获得发送者的地址,recvfrom通常用于无连接套接字。否则,recvfrom等同于recv。 二、 小结 这里面再提一个带外数据,感兴趣的同志可以自行百度。 之前写过一个server和client的例子,连接如下,可对应本文做对比阅读。 LinuxSocket Server 与 Client 例子 个人觉得这只是套接字的入门,如果一个服务器要连接多个客户端呢?以后有机会和大家一起分享下select的套接字用法。

    时间:2020-07-07 关键词: Linux api c socket

  • 网络编程你有没有理解的透彻

    进行程序开发的同学,无论Web前端开发、Web后端开发,还是搜索引擎和大数据,几乎所有的开发领域都会涉及到网络编程。比如我们进行Web服务端开发,除了Web协议本身依赖网络外,通常还需要连接数据库,而数据库连接通常是通过网络连接数据库服务器,或者数据库集群,如果负载太高还要搞个缓存集群。 我们在上学的时候基本学了网络编程和网络协议。但两者之间的具体关系可能有些摸不到头脑。这里我们首先重点介绍2个概念,一个概念是网络编程,另外一个是协议。 我们知道网络协议是一个分层的协议族,也就是是有一组协议构成,从下往上各自负责各自的功能。那什么是协议呢?协议的字面意思是共同计议,商议。简单的理解其实就是多方进行沟通的规定。而网络协议其实就是在网络中多个计算节点进行交互、沟通的规定。如果根我们日常生活对比的话,协议可以理解为语言,比如汉语普通话。两个人交流如果都用不通话,那么彼此都能理解对方表达的意图。例如,一个人用四川话,而另外一个用浙江话,那沟通起来估计几乎不太可能。网络协议也是一样的,通过对数据格式的规范化,从而使计算机之间能够彼此明确对方的意图。 下面本文介绍一下网络编程,网络编程也称为socket编程,socket通常译作“套接字”,但原意其实意译应该为”接口“。也就是操作系统提供给开发人员进行网络开发的API接口。这套接口通常可以参数的调整支持多种协议,包括TCP、UDP和IP等等。下面本文从套接字编程和协议两方面分别详细的进行介绍。 网络编程 为了便于理解,本文先从具体的内容开始,也就是通过一个实例介绍一下网络编程是怎么回事。 本文将以TCP协议为例介绍网络编程和协议之前的关系。为了简单,便于理解,本文以Python为例进行介绍,如果不了解Python编程语言关系也不大,下面代码很容易理解。我们知道在网络通信中无论是BS架构还是CS架构,通常分为服务端和客户端,只不过BS架构中的浏览器就是客户端。因此,本文的示例也包含服务端和客户端2部分的代码。代码功能很简单,就是实现客户端和服务端发送字符串。 客户端服务端通信模型 这个代码清单是服务端的代码,这段代码的作用就是在服务端的某个端口建立监听,并等待客户端建立连接。完成连接建立后,等待客户端发送数据,并将数据回传给客户端。 #!/usr/bin/env python3#-*- coding:utf-8 -*-from socket import *from time import cTImehost = ‘’port = 12345buffsize = 2048ADDR = (host,port)# 创建一个基于TCP协议的套接字tcTIme = socket(AF_INET,SOCK_STREAM)tcTIme.bind(ADDR)# 在指定的地址和端口监听tcTIme.listen(3)while True:print(‘Wait for connection 。..’) tctimeClient,addr = tctime.accept()print(“Connection from :”,addr) while True: data = tctimeClient.recv(buffsize).decode() if not data: breaktctimeClient.send((‘[%s] %s’ % (ctime(),data)).encode())tctimeClient.close()tctimeClient.close() 阅读服务端的代码可以看出主要包括,socket、bind、listen、accept、recv和send几个。其中值得关注的是listen和accept,两者分别用于监听端口和接受客户端的连接请求。 下面代码清单是客户端的实现,这里特别的地方是有一个connect函数,该函数实现与服务端建立连接。 #!/usr/bin/env python3#-*- coding:utf-8 -*-from socket import *HOST =‘localhost’PORT = 12345BUFFSIZE=2048ADDR = (HOST,PORT)tctimeClient = socket(AF_INET,SOCK_STREAM)tctimeClient.connect(ADDR)while True:data = input(“》”) if not data: breaktctimeClient.send(data.encode()) data = tctimeClient.recv(BUFFSIZE).decode() if not data: breakprint(data)tctimeClient.close() 通过上述示例代码可以看出服务端通常是被动的,而客户端则要主动一些。服务端程序建立对某个端口的监听,等待客户端的连接请求。客户端向服务端发送连接请求,不出意外的情况下连接建立成功,这时客户端和服务端之前就可以互发数据了。当然,在实际生产环境中意外是经常的,因此从协议和接口层面,需要处理各种意外,本文在协议部分将详细介绍。 另外,本文实现了一个基本的客户端和服务端通信的程序,这个模式的通信在实际生产中几乎不再使用。在实际生产中为了提高数据传输和处理的效率,通常采用异步模式,这些内容超出了本文的介绍范围,后续文章会逐渐介绍。 TCP协议详解 前文说了网络协议是网络中不同计算机信息通信的语言,为了实现交互,这个语言就需要有一定的格式。本文以TCP协议为例进行介绍。 TCP协议是一个可靠的传输协议,其可靠性表现在2方面,一方面是保证数据包可以按照发送的顺序到达,另外一方面是保证数据包一定程度的正确性(后文详解为什么是一定程度上的正确性)。其可靠性的实现则基于2点技术,一点是具有一个CRC校验,这样如果数据包中的某些数据出现错误可以通过该校验和发现;另外一点是每个数据包都有一个序号,这样就能保证数据包的顺序性,如果出现错位的数据包可以请求重发。 既然说到了格式,那我们先看一下TCP数据包的数据格式。如下图是TCP数据包的格式,包括原端口、目的端口、序列号和标识位等等内容,内容有些多,看着可能有点眼花。但从大的方面理解,这个数据包其实只包含2部分内容,一个是包头,另外一个则是具体需要传输的数据。在TCP协议的控制逻辑中,包头起着最为关键的作用,它是TCP协议中诸如建立连接、断开连接、重传和错误校验等各种特性的基础。 包头的其它信息的含义都比较明了,本文仅仅介绍几个标志位(URG、ACK、PSH、RST、SYN和FIN)的含义。具体含义如下: ACK: 确认序号有效。 RST:重置连接 SYN:发起一个新连接 FIN:释放一个连接 连接的建立TCP在具体传输数据之前需要建立连接。这里的连接并不是物理连接,物理连接基于底层的协议已经建立完成,而且TCP建立连接也是要假设底层连接已经成功,TCP的连接其实是一个虚拟的,逻辑的连接。简单粗暴的理解,就是客户端和服务端分别记录了各自接受到的数据包的序号,并且将自身设置为某种状态。在TCP协议中,连接的建立通常成为3次握手,从字面的概念可以看出,连接的建立需要经过3次确认的过程。 TCP协议3次握手的过程如图所示,初始状态客户端和服务端都处于关闭状态。主要过程分为3步: 客户端发送预连接数据包: TCP的连接是由客户端主动发起建立,客户端会发送一个数据包(报文)给服务端,需要注意的是数据包中的SYN标识位为1。我们前文已经介绍,如果SYN为1,则说明为建立连接的数据包。同时,在该数据包中包含一个请求序列号,该序列号也是建立连接的依据。 服务端回复连接确认: 服务端确认可以建立连接(服务端不一定可以建立连接,因为系统中套接字的数量是有限的)的情况下会向客户端发送一个应答数据包。在应答数据包中会将ACK标志位设置为1,表示为服务端应答数据包。同时,在应答数据包中会设置请求序列号和应答序列号的值,具体参考图3. 客户端回复连接确认: 最后,客户端再次发送一个连接确认数据包,告诉服务端连接建立成功。 从上面流程可以看出,连接的建立需要经过多次交互,这就是我们日常中所说的建立连接是高成本的操作。在实际生产环境中,为了应对这个问题,会减少连接建立的频度,通常的做法是建立连接池,传输数据时直接从连接池中获取连接,而不是新建连接。 有人可能觉得可以对建立连接的过程进行优化,比如将客户端最后一次的确认取消掉,觉得这个没有卵用。对于正常情况确实没有多大的作用,这里主要是应对异常情况。因为网络拓扑是非常复杂的,特别是在广域网中,有着数不清的网络节点,因此会出现各种异常情况。因此,TCP协议在设计的时候必须要保证异常情况下的可靠性。 我们这里举一个例子,就是连接请求超时的情况。假设客户端向服务端发送一个连接请求,由于各种原因,请求一直没有到达服务端,因此服务端也就没有回复连接确认消息。客户端连接超时,因此客户端重新发送一个连接请求到服务端,这次比较顺利,很快到达了,并且顺利建立了连接。之后,前一个数据包经过长途跋涉最终还是到了服务端,服务端也向客户端发送了回复数据包,服务端认为连接是建立成功的,并且会维持连接。但客户端层面认为连接是超时的,因此将永远不会关闭该连接。这样就会造成服务端有残留的资源,从而造成服务端资源浪费,久而久之可能会导致服务端无新连接资源可用。 另外一个需要说明的是客户端和服务端的套接字都有相应的状态,而且状态会随着连接的不同阶段变化。初始状态都是CLOSE,最终连接建立成功后都是ESTABLISHED,具体变化过程如图3所示。后面本文会详细介绍状态变化情况。 传输数据完成连接建立之后,客户端和服务端就可以进行数据传输了。我们知道TCP是可靠的传输,那么传输的可靠性是通过什么来保证的呢?主要就是通过包头中的校验和、请求序列号和应答序列号(参考图2)。 TCP数据内容的可靠性是通过校验和保证的。TCP在发送数据时都会计算整个数据包的校验和,并存储在包头的校验和字段中。接收方会按照规则进行计算,从而确认接收到的数据是否是正确的。发送发计算校验和的流程大概如下: 把伪首部、TCP包头和TCP数据分为16为的字,并把TCP包头中的校验和字段置0 用反码加法累加所有16位数字 对计算结果去反,将其填充到TCP包头的校验和字段 接收方将所有原码相加,高位叠加,如果全为1则表示数据正确,否则说明数据有错误。 TCP数据包顺序的可靠性是通过请求序列号和应答序列号保证的。在数据传输中的每个请求都会有一个请求序列号,而在接收方接收到数据后会发送一个应答序列号,这样发送方就能知道数据是否被正确接收,而接收方也能知道数据是否出现乱序,从而保证数据包的顺序性。 断开连接TCP关闭连接分为4步,称为4次挥手。连接的关闭不一定是在客户端发起,服务端也可以发起关闭连接。关闭连接的过程如下: 发起方发送一个FIN置位的数据包,用来请求关闭发送方到接收方的连接 接收方发送一个应答,ACK标志位为1,确认关闭。此时完成了发起方到接收方的连接,也即发送方无法再向接收方发送数据,但接收方还可以向发送方发送数据。 接收方数据传输完成后向发起方发送一个FIN为1的包,表示请求断开连接 发起方回复一个ACK包,确认关闭成功 关闭连接流程示意图 TCP是全双工通信,因此关闭连接时需要双向关闭连接。首先是关闭发起方关闭本端的连接,然后是关闭接收方在收到发起方的关闭请求后,除了回复关闭应答外,还要确保数据传输完成后发起一个关闭连接的请求,保证双向同时关闭。 截止到这里,本文介绍了基于TCP协议进行网络编程的主要内容。当然这个只是入门级的,如果需要真正理解TCP协议和网络编程还需要学习很多内容。后续本号将陆续介绍给大家。

    时间:2020-05-14 关键词: 网络编程 socket

  • Linux下Socket编程

    一、基本socket函数 Linux系统是通过提供套接字(socket)来进行网络编程的。网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符。socket也有一个类似于打 开文件的函数:socket(),调用socket(),该函数返回一个整型的socket的描述符,随后的连接建立、数据传输等操作也都是通过该socket实现。 1、socket函数 syntax:    int socket(int domain, int type, int protocol); 功能说明:    调用成功,返回socket文件描述符;失败,返回-1,并设置errno 参数说明:   domain指明所使用的协议族,通常为PF_INET,表示TCP/IP协议;   type参数指定socket的类型,基本上有三种:数据流套接字、数据报套接字、原始套接字   protocol通常赋值"0"。   两个网络程序之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口。socket数据结构中包含这五种信息。 2、bind函数 syntax:      int bind(int sock_fd,struct sockaddr_in *my_addr, int addrlen); 功能说明:    将套接字和指定的端口相连。成功返回0,否则,返回-1,并置errno. 参数说明:     sock_fd是调用socket函数返回值,   my_addr是一个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针;   struct sockaddr_in结构类型是用来保存socket信息的:   struct sockaddr_in {   short int sin_family;   unsigned short int sin_port;   struct in_addr sin_addr;   unsigned char sin_zero[8];   };     addrlen为sockaddr的长度。 3、connect函数 syntax:       int connect(int sock_fd, struct sockaddr *serv_addr,int addrlen); 功能说明:    客户端发送服务请求。成功返回0,否则返回-1,并置errno。 参数说明:    sock_fd 是socket函数返回的socket描述符;serv_addr是包含远端主机IP地址和端口号的指针;addrlen是结构sockaddr_in的长度。 4、listen函数 syntax:    int listen(int sock_fd, int backlog); 功能说明:    等待指定的端口的出现客户端连接。调用成功返回0,否则,返回-1,并置errno. 参数说明:    sock_fd 是socket()函数返回值;    backlog指定在请求队列中允许的最大请求数 5、accecpt函数 syntax:      int accept(int sock_fd, struct sockadd_in* addr, int addrlen); 功能说明:    用于接受客户端的服务请求,成功返回新的套接字描述符,失败返回-1,并置errno。 参数说明:    sock_fd是被监听的socket描述符,    addr通常是一个指向sockaddr_in变量的指针,    addrlen是结构sockaddr_in的长度。 6、write函数 syntax:     ssize_t write(int fd,const void *buf,size_t nbytes) 功能说明:     write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数.失败时返回-1. 并设置errno变量.     在网络程序中,当我们向套接字文件描述符写时有俩种可能:       1)write的返回值大于0,表示写了部分或者是全部的数据.       2)返回的值小于0,此时出现了错误.需要根据错误类型来处理.         如果错误为EINTR表示在写的时候出现了中断错误.         如果错误为EPIPE表示网络连接出现了问题. 7、read函数 syntax:     ssize_t read(int fd,void *buf,size_t nbyte) 函数说明:     read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0 表示已经读到文件的结束了,小于0表示出现了错误.     如果错误为EINTR说明读是由中断引起的,     如果错误是ECONNREST表示网络连接出了问题. 8、close函数 syntax: int close(sock_fd); 说明: 当所有的数据操作结束以后,你可以调用close()函数来释放该socket,从而停止在该socket上的任何数据操作: 函数运行成功返回0,否则返回-1 二、socket编程的其他函数说明 1、 网络字节顺序及其转换函数 1) 网络字节顺序 每一台机器内部对变量的字节存储顺序不同,而网络传输的数据是一定要统一顺序的。所以对内部字节表示顺序与网络字节顺序不同的机器, 一定要对数据进行转换,从程序的可移植性要求来讲,就算本机的内部字节表示顺序与网络字节顺序相同也应该在传输数据以前先调用数据转换函数, 以便程序移植到其它机器上后能正确执行。真正转换还是不转换是由系统函数自己来决定的。 2) 有关的转换函数 * unsigned short int htons(unsigned short int hostshort): 主机字节顺序转换成网络字节顺序,对无符号短型进行操作4bytes * unsigned long int htonl(unsigned long int hostlong): 主机字节顺序转换成网络字节顺序,对无符号长型进行操作8bytes * unsigned short int ntohs(unsigned short int netshort): 网络字节顺序转换成主机字节顺序,对无符号短型进行操作4bytes * unsigned long int ntohl(unsigned long int netlong): 网络字节顺序转换成主机字节顺序,对无符号长型进行操作8bytes 注:以上函数原型定义在netinet/in.h里 2、IP地址转换 有三个函数将数字点形式表示的字符串IP地址与32位网络字节顺序的二进制形式的IP地址进行转换 (1) unsigned long int inet_addr(const char * cp):该函数把一个用数字和点表示的IP地址的字符串转换成一个无符号长整型,如:struct sockaddr_in ina ina.sin_addr.s_addr=inet_addr("202.206.17.101") 该函数成功时:返回转换结果;失败时返回常量INADDR_NONE,该常量=-1,二进制的无符号整数-1相当于255.255.255.255,这是一个广播地址,所以在程序中调用iner_addr()时,一定要人为地对调用失败进行处理。由于该函数不能处理广播地址,所以在程序中应该使用函数inet_aton()。 (2)int inet_aton(const char * cp,struct in_addr * inp):此函数将字符串形式的IP地址转换成二进制形式的IP地址;成功时返回1,否则返回0,转换后的IP地址存储在参数inp中。 (3) char * inet_ntoa(struct in-addr in):将32位二进制形式的IP地址转换为数字点形式的IP地址,结果在函数返回值中返回,返回的是一个指向字符串的指针。 3、字节处理函数 Socket地址是多字节数据,不是以空字符结尾的,这和C语言中的字符串是不同的。Linux提供了两组函数来处理多字节数据,一组以b(byte)开头,是和BSD系统兼容的函数,另一组以mem(内存)开头,是ANSI C提供的函数。 以b开头的函数有: (1) void bzero(void * s,int n):将参数s指定的内存的前n个字节设置为0,通常它用来将套接字地址清0。 (2) void bcopy(const void * src,void * dest,int n):从参数src指定的内存区域拷贝指定数目的字节内容到参数dest指定的内存区域。 (3) int bcmp(const void * s1,const void * s2,int n):比较参数s1指定的内存区域和参数s2指定的内存区域的前n个字节内容,如果相同则返回0,否则返回非0。 注:以上函数的原型定义在strings.h中。 以mem开头的函数有: (1) void * memset(void * s,int c,size_t n):将参数s指定的内存区域的前n个字节设置为参数c的内容。 (2) void * memcpy(void * dest,const void * src,size_t n):功能同bcopy(),区别:函数bcopy()能处理参数src和参数dest所指定的区域有重叠的情况,memcpy()则不能。 (4) int memcmp(const void * s1,const void * s2,size_t n):比较参数s1和参数s2指定区域的前n个字节内容,如果相同则返回0,否则返回非0。 注:以上函数的原型定义在string.h中。 二、程序说明 本使用tcp协议进行通信,服务端进行监听,在收到客户端的连接后,发送数据给客户端;客户端在接受到数据后打印出来,然后关闭。 1、client.c #include #include #include #include #include #include int main() { int cfd; int recbytes; int sin_size; char buffer[1024]={0}; struct sockaddr_in s_add,c_add; unsigned short portnum=0x8888; printf("Hello,welcome to client !rn"); cfd = socket(AF_INET, SOCK_STREAM, 0); if(-1 == cfd) { printf("socket fail ! rn"); return -1; } printf("socket ok !rn"); bzero(&s_add,sizeof(struct sockaddr_in)); s_add.sin_family=AF_INET; s_add.sin_addr.s_addr= inet_addr("192.168.1.2"); s_add.sin_port=htons(portnum); printf("s_addr = %#x ,port : %#xrn",s_add.sin_addr.s_addr,s_add.sin_port); if(-1 == connect(cfd,(struct sockaddr *)(&s_add), sizeof(struct sockaddr))) { printf("connect fail !rn"); return -1; } printf("connect ok !rn"); if(-1 == (recbytes = read(cfd,buffer,1024))) { printf("read data fail !rn"); return -1; } printf("read okrnREC:rn"); buffer[recbytes]=''; printf("%srn",buffer); getchar(); close(cfd); return 0; } 2、server.c #include #include #include #include #include #include int main() { int sfp,nfp; struct sockaddr_in s_add,c_add; int sin_size; unsigned short portnum=0x8888; printf("Hello,welcome to my server !rn"); sfp = socket(AF_INET, SOCK_STREAM, 0); if(-1 == sfp) { printf("socket fail ! rn"); return -1; } printf("socket ok !rn"); bzero(&s_add,sizeof(struct sockaddr_in)); s_add.sin_family=AF_INET; s_add.sin_addr.s_addr=htonl(INADDR_ANY); s_add.sin_port=htons(portnum); if(-1 == bind(sfp,(struct sockaddr *)(&s_add), sizeof(struct sockaddr))) { printf("bind fail !rn"); return -1; } printf("bind ok !rn"); if(-1 == listen(sfp,5)) { printf("listen fail !rn"); return -1; } printf("listen okrn"); while(1) { sin_size = sizeof(struct sockaddr_in); nfp = accept(sfp, (struct sockaddr *)(&c_add), &sin_size); if(-1 == nfp) { printf("accept fail !rn"); return -1; } printf("accept ok!rnServer start get connect from %#x : %#xrn",ntohl(c_add.sin_addr.s_addr),ntohs(c_add.sin_port)); if(-1 == write(nfp,"hello,welcome to my server rn",32)) { printf("write fail!rn"); return -1; } printf("write ok!rn"); close(nfp); } close(sfp); return 0; } 在cygwin下,使用gcc命令编译如下: gcc -o server server.c gcc -o client client.c 然后运行程序: ./server ./client server执行效果如下: Hello,welcome to my server ! socket ok ! bind ok ! listen ok accept ok! Server start get connect from 0xc0a80102 : 0xc927 write ok! client执行效果如下: Hello,welcome to client ! socket ok ! s_addr = 0x201a8c0 ,port : 0x8888 connect ok ! read ok REC: hello,welcome to my server 本文欢迎转载,转载请注明出处和作者 出处:http://blog.sina.com.cn/staratsky

    时间:2019-09-11 关键词: Linux socket

  • 实战Linux Bluetooth编程(五) Socket与Bluetooth

    作者: Sam (甄峰) sam_code@hotmail.com   Linux下Bluetooth编程,借用了Socket体制。也就是说,BlueZKernel部分将Bluetooth协议栈以网络协议的形式添加进网络协议栈,这样极大的方便了用户编程。下面Sam就结合Socket概念将LinuxBluetooth做个研究。   1957年10月4日,星期五,苏联发射了人类历史上第一颗人造地球卫星--Sputnik.这标志着人类外太空时代的开始。这颗卫星篮球大小,在发射98分钟后到达运转轨道,可以通过短波40.002MHz收听到它的声音。这也标志着苏联在航天科技领域超过美国。但当时谁能想到,Sputnik的升空竟然促进了TCP/IP和Internel的出现。(Sam:不知道朝鲜那个轨道高度几百米的卫星会促成什么出现,嘿嘿)。被Sputnik所刺激的美国总统艾森豪威尔五星上将积极推动ARPA。又因为美国政府为了公平起见,每次采购计算机时都从不同设备制造商处购买。大家很快发现,各个计算机无法兼容。1962年,Licklider提出:各个计算机高度自治,但他们也应该能够相互通讯。这就是ARPA网,它成为Internel的前身。     一:理解Socket: 在使用手机与女朋友联系时,必须用手机拨她的号码,然后心情坎坷的等待她的应答。当双方通话时,就建立了一个具有两个端点的通信线路。 Linux中的Socket与电话非常相似。具体问题,稍后再分析。   二:Socket域(domain),类型(type),协议(protoclo)以及Bluetooth中的具体使用: Berkeley小组在构思BSDSocket时,TCP/IP协议也还处在发展之中,其他一些很有竞争力的协议如X.25等也在发展,其它很多协议还在构思与研究阶段(Bluetooth还没出生)。为了使Socket可以应用于各种不同协议,domain的作用就在于此。 domain指出想要使用的协议族。 不得不佩服Berkeley小组的前瞻力。他们考虑在指定Socket时,可能还需要进一步的细分类目: 1.某个协议族(Domain)中的一个或多个协议。 2.某个协议中的一个或多个地址格式。 这个规则在TCP/IP等协议栈时并不明显,因为某个协议族只有同一种地址格式。但在Bluetooth中则非常有用。   protocol则用来指出在此协议族中的具体某个协议。 虽然在TCP/IP协议栈中,因为协议族中某个type的协议栈只有一种,所以此项为0,但Bluetooth中,这一项则非常有用。   type用来指出此协议族中的具体协议的Socket类型为何种:SOCK_STREAM,SOCK_DGRAM,SOCK_SEQPACKET,SOCK_RAW.   三:Socket地址: 每一种通信协议都对网络地址格式作了明确规定。协议族(Domain)+协议(protocol)的作用就是指明使用哪种地址类型。   BSD Socket是在ANSI C标准被采纳之前开发的,所以没有使用(void*)数据类型来接收结构化的地址。BSD的解决方案是定义了一个通用的地址结构: struct sockaddr {   sa_family_t sa_family; //地址族   charsa_data[14];   //地址数据 }; sa_family长度2字节,用来存放地址族。 sa_data长度14字节,用来存放具体的协议的地址数据。   如果是用AF_INET(IPV4),则它的地址类型sockaddr_in如下,刚好与struct sockaddr对应 struct sockaddr_in {   sa_family_tsin_family;   //地址族   uint16_tsip_port;        //端口   struct in_addrsin_addr;   //Internel 地址   unsigned char sin_zero[8]; //占位字节 };   如果是用Bluetooth协议族(PF_BLUETOOTH)中的协议l2cap(BTPROTO_L2CAP),则地址格式如下: struct sockaddr_l2 {  sa_family_t l2_family; //地址族  unsignedshort l2_psm;  //PSM  bdaddr_t l2_bdaddr;    //Bluetooth 地址  unsigned short l2_cid; };     四:BluetoothSocket的建立和地址绑定: int socket(int domain, int type, int protocol); domain:使用 PF_BLUETOOTH。 protocol:使用想要建立的Socket的protocol.如果想建立HCISocket:BTPROTO_HCI。L2cap:BTPROTO_L2CAP type:SOCK_SEQPACKET,以Packet为单位读取。SOCK_SAW:原始Socket。   int bind(int sockfd, const struct sockaddr *my_addr, socklen_taddrlen); 将socket与某个地址绑定。 嘿嘿,接着前面Socket与手机的话题,建立一个Socket。就相当于是一个手机,地址,则相当于手机号码。 一个手机想要别人打进来,就需要让别人知道电话号码。 而一个Bluetooth设备想要别人能够连接,也需要将Socket与Bluetooth地址绑定。 山寨机让我们知道了双卡双待,Bluetooth也可以实现这一点。建立一个Socket,只是一个手机,它可以与多个bdaddr绑定。这就是hci0,hci1等等。   五:理解网络字序: 对于多字节数据,不同的CPU有不同的组织方式,最基本的字节序位: 小端(little-endian): 将低序字节存储在起始位置。 大端(big-endian):将高序字节存储在其实位置。   Intel CPU使用小端。Motorola等CPU使用大端,网络上传输数据的标准顺序为大端。   他们之间的转化: htobs(), htonl() 主机到网络 ntohl() , ntohs() 网络到主机。

    时间:2019-09-11 关键词: 编程 socket

  • Linux下获取多网卡信息

    支持多网卡,主要是使用ioctl函数系统调用实现,通过指定设备名实现指定功能.之前使用socket()函数,获取文件描述符.在此基础可以很轻松的扩展,如获取net mask,MAC address等   #include stdio.h   #include sys/types.h   #include sys/param.h      #include sys/ioctl.h   #include sys/socket.h   #include net/if.h   #include netinet/in.h   #include net/if_arp.h      #define MAXINTERFACES 16      int main(void)   {    register int fd, intrface;    struct ifreq buf[MAXINTERFACES];    struct ifconf ifc;       if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)    {    return -1;    }       ifc.ifc_len = sizeof(buf);    ifc.ifc_buf = (caddr_t) buf;    if (ioctl (fd, SIOCGIFCONF, (char *) &ifc) < 0)    {    return -1;    }       intrface = ifc.ifc_len / sizeof (struct ifreq);    printf("number of interface is: %dn",intrface);    while (intrface-- > 0)    {    printf ("net device %sn", buf[intrface].ifr_name);       if ((ioctl (fd, SIOCGIFFLAGS, (char *) &buf[intrface])) < 0)    {    continue;    }       if (buf[intrface].ifr_flags & IFF_PROMISC)    {    puts ("the interface is PROMISC");    }    else    {    if (buf[intrface].ifr_flags & IFF_UP)    {    puts("the interface status is UP");    }    else    {    if (buf[intrface].ifr_flags & IFF_RUNNING)    puts("the interface status is RUNNING");    }    }       if (!(ioctl (fd, SIOCGIFADDR, (char *) &buf[intrface])))    {    puts ("IP address is:");    puts(inet_ntoa(((struct sockaddr_in*)(&buf[intrface].ifr_addr))->sin_addr));    puts("");    }    else    {    char str[256];    sprintf (str, "cpm: ioctl device %s", buf[intrface].ifr_name); perror (str);    }      }   close (fd);   return 0;      }

    时间:2019-08-26 关键词: Linux socket

  • Linux系统调用列表

    以下是Linux系统调用的一个列表,包含了大部分常用系统调用和由系统调用派生出的的函数。这可能是你在互联网上所能看到的唯一一篇中文注释的Linux系统调用列表,即使是简单的字母序英文列表,能做到这么完全也是很罕见的。按照惯例,这个列表以man pages第2节,即系统调用节为蓝本。按照笔者的理解,对其作了大致的分类,同时也作了一些小小的修改,删去了几个仅供内核使用,不允许用户调用的系统调用,对个别本人稍觉不妥的地方作了一些小的修改,并对所有列出的系统调用附上简要注释。其中有一些函数的作用完全相同,只是参数不同。(可能很多熟悉C++朋友马上就能联想起函数重载,但是别忘了Linux核心是用C语言写的,所以只能取成不同的函数名)。还有一些函数已经过时,被新的更好的函数所代替了(gcc在链接这些函数时会发出警告),但因为兼容的原因还保留着,这些函数我会在前面标上“*”号以示区别。一、进程控制:fork创建一个新进程clone按指定条件创建子进程execve运行可执行文件exit中止进程_exit立即中止当前进程getdtablesize进程所能打开的最大文件数getpgid获取指定进程组标识号setpgid设置指定进程组标志号getpgrp获取当前进程组标识号setpgrp设置当前进程组标志号getpid获取进程标识号getppid获取父进程标识号getpriority获取调度优先级setpriority设置调度优先级modify_ldt读写进程的本地描述表nanosleep使进程睡眠指定的时间nice改变分时进程的优先级pause挂起进程,等待信号personality设置进程运行域prctl对进程进行特定操作ptrace进程跟踪sched_get_priority_max取得静态优先级的上限sched_get_priority_min取得静态优先级的下限sched_getparam取得进程的调度参数sched_getscheduler取得指定进程的调度策略sched_rr_get_interval取得按RR算法调度的实时进程的时间片长度sched_setparam设置进程的调度参数sched_setscheduler设置指定进程的调度策略和参数sched_yield进程主动让出处理器,并将自己等候调度队列队尾vfork创建一个子进程,以供执行新程序,常与execve等同时使用wait等待子进程终止wait3参见waitwaitpid等待指定子进程终止wait4参见waitpidcapget获取进程权限capset设置进程权限getsid获取会晤标识号setsid设置会晤标识号二、文件系统控制1、文件读写操作fcntl文件控制open打开文件creat创建新文件close关闭文件描述字read读文件write写文件readv从文件读入数据到缓冲数组中writev将缓冲数组里的数据写入文件pread对文件随机读pwrite对文件随机写lseek移动文件指针_llseek在64位地址空间里移动文件指针dup复制已打开的文件描述字dup2按指定条件复制文件描述字flock文件加/解锁pollI/O多路转换truncate截断文件ftruncate参见truncateumask设置文件权限掩码fsync把文件在内存中的部分写回磁盘2、文件系统操作access确定文件的可存取性chdir改变当前工作目录fchdir参见chdirchmod改变文件方式fchmod参见chmodchown改变文件的属主或用户组fchown参见chownlchown参见chownchroot改变根目录stat取文件状态信息lstat参见statfstat参见statstatfs取文件系统信息fstatfs参见statfsreaddir读取目录项getdents读取目录项mkdir创建目录mknod创建索引节点rmdir删除目录rename文件改名link创建链接symlink创建符号链接unlink删除链接readlink读符号链接的值mount安装文件系统umount卸下文件系统ustat取文件系统信息utime改变文件的访问修改时间utimes参见utimequotactl控制磁盘配额三、系统控制ioctlI/O总控制函数_sysctl读/写系统参数acct启用或禁止进程记账getrlimit获取系统资源上限setrlimit设置系统资源上限getrusage获取系统资源使用情况uselib选择要使用的二进制函数库ioperm设置端口I/O权限iopl改变进程I/O权限级别outb低级端口操作reboot重新启动swapon打开交换文件和设备swapoff关闭交换文件和设备bdflush控制bdflush守护进程sysfs取核心支持的文件系统类型sysinfo取得系统信息adjtimex调整系统时钟alarm设置进程的闹钟getitimer获取计时器值setitimer设置计时器值gettimeofday取时间和时区settimeofday设置时间和时区stime设置系统日期和时间time取得系统时间times取进程运行时间uname获取当前UNIX系统的名称、版本和主机等信息vhangup挂起当前终端nfsservctl对NFS守护进程进行控制vm86进入模拟8086模式create_module创建可装载的模块项delete_module删除可装载的模块项init_module初始化模块query_module查询模块信息*get_kernel_syms取得核心符号,已被query_module代替四、内存管理brk改变数据段空间的分配sbrk参见brkmlock内存页面加锁munlock内存页面解锁mlockall调用进程所有内存页面加锁munlockall调用进程所有内存页面解锁mmap映射虚拟内存页munmap去除内存页映射mremap重新映射虚拟内存地址msync将映射内存中的数据写回磁盘mprotect设置内存映像保护getpagesize获取页面大小sync将内存缓冲区数据写回硬盘cacheflush将指定缓冲区中的内容写回磁盘五、网络管理getdomainname取域名setdomainname设置域名gethostid获取主机标识号sethostid设置主机标识号gethostname获取本主机名称sethostname设置主机名称六、socket控制socketcallsocket系统调用socket建立socketbind绑定socket到端口connect连接远程主机accept响应socket连接请求send通过socket发送信息sendto发送UDP信息sendmsg参见sendrecv通过socket接收信息recvfrom接收UDP信息recvmsg参见recvlisten监听socket端口select对多路同步I/O进行轮询shutdown关闭socket上的连接getsockname取得本地socket名字getpeername获取通信对方的socket名字getsockopt取端口设置setsockopt设置端口参数sendfile在文件或端口间传输数据socketpair创建一对已联接的无名socket七、用户管理getuid获取用户标识号setuid设置用户标志号getgid获取组标识号setgid设置组标志号getegid获取有效组标识号setegid设置有效组标识号geteuid获取有效用户标识号seteuid设置有效用户标识号setregid分别设置真实和有效的的组标识号setreuid分别设置真实和有效的用户标识号getresgid分别获取真实的,有效的和保存过的组标识号setresgid分别设置真实的,有效的和保存过的组标识号getresuid分别获取真实的,有效的和保存过的用户标识号setresuid分别设置真实的,有效的和保存过的用户标识号setfsgid设置文件系统检查时使用的组标识号setfsuid设置文件系统检查时使用的用户标识号getgroups获取后补组标志清单setgroups设置后补组标志清单八、进程间通信ipc进程间通信总控制调用1、信号sigaction设置对指定信号的处理方法sigprocmask根据参数对信号集中的信号执行阻塞/解除阻塞等操作sigpending为指定的被阻塞信号设置队列sigsuspend挂起进程等待特定信号signal参见signalkill向进程或进程组发信号*sigblock向被阻塞信号掩码中添加信号,已被sigprocmask代替*siggetmask取得现有阻塞信号掩码,已被sigprocmask代替*sigsetmask用给定信号掩码替换现有阻塞信号掩码,已被sigprocmask代替*sigmask将给定的信号转化为掩码,已被sigprocmask代替*sigpause作用同sigsuspend,已被sigsuspend代替sigvec为兼容BSD而设的信号处理函数,作用类似sigactionssetmaskANSI C的信号处理函数,作用类似sigaction2、消息msgctl消息控制操作msgget获取消息队列msgsnd发消息msgrcv取消息3、管道pipe创建管道4、信号量semctl信号量控制semget获取一组信号量semop信号量操作5、共享内存shmctl控制共享内存shmget获取共享内存shmat连接共享内存shmdt拆卸共享内存

    时间:2019-07-09 关键词: Linux socket

  • C# Socket Clinet编写

    最近有段时间因为有个项目一直需要Socket数据传输。所以呢没办法就整了一套Socket最简单的版本出来。以便自己日后方便使用。我遇到的程序Socket是通过Tcp Ip的方式进行数据传输的.不多说先上图当输入IP跟端口之后进行连接button事件:        private void Open_Click(object sender, EventArgs e)        {            if (IP.Text != "" && Port.Text != "")            {                Open.Enabled = false;                Close.Enabled = true;                //实例化 套接字                sokClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);                //创建 ip对象                IPAddress address = IPAddress.Parse(IP.Text.Trim());                //创建网络节点对象 包含 ip和port                IPEndPoint endpoint = new IPEndPoint(address, int.Parse(Port.Text.Trim()));                //连接 服务端监听套接字                sokClient.Connect(endpoint);                //创建负责接收 服务端发送来数据的 线程                threadClient = new Thread(ReceiveMsg);                threadClient.IsBackground = true;                //如果在win7下要通过 某个线程 来调用 文件选择框的代码,就需要设置如下                threadClient.SetApartmentState(ApartmentState.STA);                threadClient.Start();            }            else            {                MessageBox.Show("请将端口跟IP地址填写完整!");            }        }连接上之后填写内容点击发送按钮button事件如下:        private void button1_Click(object sender, EventArgs e)        {            if (txtInput.Text != "")            {                string Timer = DateTime.Now.ToString();            // 2008-9-4 20:02:10                txtShow.AppendText("Client " + Timer + ":" + txtInput.Text.Trim() + "rn");                byte[] arrMsg = System.Text.Encoding.Default.GetBytes(txtInput.Text.Trim() + "rn");//这里可以根据客户的需求进行格式的转换                sokClient.Send(arrMsg);            }        }结束数据端的部分是使用的线程处理的方式进行监听。当数据过来之后进行数据处理为:        void ReceiveMsg()        {                while (isRec)                {                    byte[] msgArr = new byte[1024 * 1024 * 1];//接收到的消息的缓冲区                    int length = 0;                    //接收服务端发送来的消息数据                    try                    {                        length = sokClient.Receive(msgArr);//Receive会阻断线程                        string strMsg = System.Text.Encoding.Default.GetString(msgArr, 0, length);//这里可以根据客户的需求进行格式的转换                        if (strMsg != "")//发送来的是文字                        {                            string Timer = DateTime.Now.ToString();            // 2008-9-4 20:02:10                            // string strMsg = System.Text.Encoding.UTF8.GetString(msgArr, 1, length - 1);                            Invoke(new Action(delegate { txtShow.AppendText("Server " + Timer + ":" + strMsg + "rn"); }));                        }                    }                    catch { }                }        }大体的主要代码就是这样了,好了。将所有的代码都贴一下方便大家使用:using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Net;using System.Net.Sockets;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Windows.Forms;namespace Socket_Client{    public partial class Form1 : Form    {        Socket sokClient = null;//负责与服务端通信的套接字        Thread threadClient = null;//负责 监听 服务端发送来的消息的线程        bool isRec = true;//是否循环接收服务端数据        void ReceiveMsg()        {                while (isRec)                {                    byte[] msgArr = new byte[1024 * 1024 * 1];//接收到的消息的缓冲区                    int length = 0;                    //接收服务端发送来的消息数据                    try                    {                        length = sokClient.Receive(msgArr);//Receive会阻断线程                        string strMsg = System.Text.Encoding.Default.GetString(msgArr, 0, length);                        if (strMsg != "")//发送来的是文字                        {                            string Timer = DateTime.Now.ToString();            // 2008-9-4 20:02:10                            // string strMsg = System.Text.Encoding.UTF8.GetString(msgArr, 1, length - 1);                            Invoke(new Action(delegate { txtShow.AppendText("Server " + Timer + ":" + strMsg + "rn"); }));                        }                    }                    catch { }                }        }        public Form1()        {            InitializeComponent();        }        private void Open_Click(object sender, EventArgs e)        {            if (IP.Text != "" && Port.Text != "")            {                Open.Enabled = false;                Close.Enabled = true;                //实例化 套接字                sokClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);                //创建 ip对象                IPAddress address = IPAddress.Parse(IP.Text.Trim());                //创建网络节点对象 包含 ip和port                IPEndPoint endpoint = new IPEndPoint(address, int.Parse(Port.Text.Trim()));                //连接 服务端监听套接字                sokClient.Connect(endpoint);                //创建负责接收 服务端发送来数据的 线程                threadClient = new Thread(ReceiveMsg);                threadClient.IsBackground = true;                //如果在win7下要通过 某个线程 来调用 文件选择框的代码,就需要设置如下                threadClient.SetApartmentState(ApartmentState.STA);                threadClient.Start();            }            else            {                MessageBox.Show("请将端口跟IP地址填写完整!");            }        }        private void Close_Click(object sender, EventArgs e)        {            Open.Enabled = true;            Close.Enabled = false;            sokClient.Close();        }        private void button1_Click(object sender, EventArgs e)        {            if (txtInput.Text != "")            {                string Timer = DateTime.Now.ToString();            // 2008-9-4 20:02:10                txtShow.AppendText("Client " + Timer + ":" + txtInput.Text.Trim() + "rn");                byte[] arrMsg = System.Text.Encoding.Default.GetBytes(txtInput.Text.Trim() + "rn");                sokClient.Send(arrMsg);            }        }        private void Form1_Load(object sender, EventArgs e)        {            Close.Enabled = false;        }    }}运行结果如下:

    时间:2019-07-08 关键词: c# socket

  • Socket实现HTTP客户端

        前些日子用 Wininet做项目。功能忒强大了。但总觉得管理Cookie有点不方便。即使设置了自己手动管理Cookies。这天上掉馅饼的事还真的常常发生。比如你之前用浏览器访问了这个站,留下了Cookie 你再用wininet访问的时候,这个馅饼就出现了。      封包不难 连接后。将 Headers一股脑堆进去。2个换行符后就是数据了(POST才有)。      服务器返回的数据,怎么知道长度呢?我们知道的有Content-Length头。但抓包发现。有些静态文件是没有的。它的这个长度保存在2个换行符之后。单独的一行以十六进制文本的格式保存。   比如: HTTP/1.1 200 OKDate: Sat, 04 Jul 2009 17:41:10 GMTServer: ApachePragma: no-cacheConnection: Keep-AliveContent-Type: text/plain     2f8 ...... 这里红色的2f8就是哦body的长度了。   控制连接行为的还有一个就是 Connection 头 如果是 Keep-Alive,则一次请求完毕后不要断开连接。我这里的做法是保存了上一次的域名和端口。如果上次请求有 Keep-Alive 而且域名和端口没变的情况下。没必要重新连接。   数据包的处理搞定了后。就是一些接口的封装了。在这里需要注意一些细节是。所有协议头不的单词的第一个字母是大写的。封装的时候没注意,走了不少弯路。   到这里已经基本满足我的项目需求了。用它做个QQ帐号注册器。速度飞快。也不会出现“非法访问”了。爽!   最后一个问题是编码识别和处理了。如果是 text 就必须有编码识别了。这部分还没实现。没找到好的解决办法。       注:上面的内容用易语言实现。需要源码可以联系我.

    时间:2019-07-08 关键词: cookies socket

  • socket错误代码对照

    Socket error 0 - Directly send errorSocket error 10004 - Interrupted function callSocket error 10013 - Permission deniedSocket error 10014 - Bad addressSocket error 10022 - Invalid argumentSocket error 10024 - Too many open filesSocket error 10035 - Resource temporarily unavailableSocket error 10036 - Operation now in progressSocket error 10037 - Operation already in progressSocket error 10038 - Socket operation on non-socketSocket error 10039 - Destination address requiredSocket error 10040 - Message too longSocket error 10041 - Protocol wrong type for socketSocket error 10042 - Bad protocol optionSocket error 10043 - Protocol not supportedSocket error 10044 - Socket type not supportedSocket error 10045 - Operation not supportedSocket error 10046 - Protocol family not supportedSocket error 10047 - Address family not supported by protocol familySocket error 10048 - Address already in useSocket error 10049 - Cannot assign requested addressSocket error 10050 - Network is downSocket error 10051 - Network is unreachableSocket error 10052 - Network dropped connection on resetSocket error 10053 - Software caused connection abortSocket error 10054 - Connection reset by peerSocket error 10055 - No buffer space availableSocket error 10056 - Socket is already connectedSocket error 10057 - Socket is not connectedSocket error 10058 - Cannot send after socket shutdownSocket error 10060 - Connection timed outSocket error 10061 - Connection refusedSocket error 10064 - Host is downSocket error 10065 - No route to hostSocket error 10067 - Too many processesSocket error 10091 - Network subsystem is unavailableSocket error 10092 - WINSOCK.DLL version out of rangeSocket error 10093 - Successful WSAStartup not yet performedSocket error 10094 - Graceful shutdown in progressSocket error 11001 - Host not foundSocket error 11002 - Non-authoritative host not foundSocket error 11003 - This is a non-recoverable errorSocket error 11004 - Valid name, no data record of requested typeWSAEADDRINUSE (10048) Address already in useWSAECONNABORTED (10053) Software caused connection abortWSAECONNREFUSED (10061) Connection refusedWSAECONNRESET (10054) Connection reset by peerWSAEDESTADDRREQ (10039) Destination address requiredWSAEHOSTUNREACH (10065) No route to hostWSAEMFILE (10024) Too many open filesWSAENETDOWN (10050) Network is downWSAENETRESET (10052) Network dropped connectionWSAENOBUFS (10055) No buffer space availableWSAENETUNREACH (10051) Network is unreachableWSAETIMEDOUT (10060) Connection timed outWSAHOST_NOT_FOUND (11001) Host not foundWSASYSNOTREADY (10091) Network sub-system is unavailableWSANOTINITIALISED (10093) WSAStartup() not performedWSANO_DATA (11004) Valid name, no data of that typeWSANO_RECOVERY (11003) Non-recoverable query errorWSATRY_AGAIN (11002) Non-authoritative host foundWSAVERNOTSUPPORTED (10092) Wrong WinSock DLL version

    时间:2019-07-04 关键词: socket

  • Socket UDP 简单聊天的实现

    服务器端:  1 #pragma comment(lib, "ws2_32.lib")   2 #include3 #include4 using namespace std;   5 SOCKET sockServer;   6 sockaddr_in addrServer;   7 sockaddr_in addrSend;   8 #define  BUF_SIZE 1024   9 #define  IP_ADDR "192.168.59.69"  10 #define  PORT 5050  11   12 void InitSocket()  13 {  14     WSADATA wsaData;  15     int erro;  16     erro = WSAStartup(MAKEWORD(2, 2), &wsaData);  17     if (erro != 0)  18     {  19         cout << "加载套接字库失败!" << endl;  20         return;  21     }  22     sockServer = socket(AF_INET, SOCK_DGRAM, 0);  23     if(sockServer == INVALID_SOCKET)  24     {  25         cout << "创建套接字失败!" << endl;  26         WSACleanup();  27         return;  28     }  29   30     addrServer.sin_family = AF_INET;  31     addrServer.sin_port = htons(PORT);  32     addrServer.sin_addr.s_addr = htonl(INADDR_ANY);  33   34     addrSend.sin_family = AF_INET;  35     addrSend.sin_port = htons(PORT+1);  36     addrSend.sin_addr.s_addr = inet_addr(IP_ADDR);  37   38     erro = bind(sockServer, (sockaddr*)&addrServer, sizeof(sockaddr));  39     if (erro == SOCKET_ERROR)  40     {  41         cout << "绑定失败!" << endl;  42         closesocket(sockServer);  43         WSACleanup();  44         return;   45     }  46 }  47   48 DWORD WINAPI RecvThread(LPVOID lParam)  49 {  50     char buf[1024];  51     int erro;  52     int len = sizeof(addrServer);  53     while(1)  54     {  55         ZeroMemory(buf, sizeof(buf));  56         erro = recvfrom(sockServer, buf, BUF_SIZE, 0, (sockaddr*)&addrSend, &len);    57         if (0 == erro)  58         {  59             cout <<"接收失败!"<< endl;  60             return 1;  61         }  62         char * ipaddr = inet_ntoa(addrSend.sin_addr);  63         if (strcmp(buf, "") != 0)  64         {  65             cout << "客户端"<< "(" << ipaddr<< "):" << buf<<endl;  66         }  67   68         Sleep(50);  69     }  70   71     return 1;  72 }  73 DWORD WINAPI SendThread(LPVOID lParam)  74 {  75     char buf[1024];  76     int erro;  77     int len = sizeof(addrServer);  78     while(1)  79     {  80         ZeroMemory(buf, sizeof(buf));  81         cin.getline(buf, 1024);  82         erro = sendto(sockServer, buf, sizeof(buf), 0, (sockaddr*)&addrSend, len);    83         if (0 == erro)  84         {  85             cout<< "发送失败!"<<endl;  86             return 1;  87         }  88         Sleep(50);  89     }  90     return 1;  91 }  92 int main()  93 {  94     InitSocket();  95     CreateThread(NULL, NULL, RecvThread, NULL, NULL, NULL);  96     CreateThread(NULL, NULL, SendThread, NULL, NULL, NULL);  97     while(1)  98     {  99         Sleep(50); 100     } 101     return 1; 102 } 客户端:  1 #pragma comment(lib, "ws2_32.lib")   2 #include3 #include4 using namespace std;   5 SOCKET sockClient;   6 sockaddr_in addrClient;   7 sockaddr_in addrSend;   8 #define  BUF_SIZE 1024  //数据缓冲区   9 #define  IP_ADDR "192.168.59.69"  //IP地址  10 #define  PORT 5050  11 void InitSocket()  12 {  13     WSADATA wsaData;  14     int erro;  15     erro = WSAStartup(MAKEWORD(2, 2), &wsaData);  16     if (erro != 0)  17     {  18         cout << "加载套接字库失败!" << endl;  19         return;  20     }  21     sockClient = socket(AF_INET, SOCK_DGRAM, 0);  22     if(sockClient == INVALID_SOCKET)  23     {  24         cout << "创建套接字失败!" << endl;  25         WSACleanup();  26         return;  27     }  28   29     addrClient.sin_family = AF_INET;//服务器端  30     addrClient.sin_port = htons(PORT);  31     addrClient.sin_addr.s_addr = inet_addr(IP_ADDR);  32   33     addrSend.sin_family = AF_INET;//客户端  34     addrSend.sin_port = htons(PORT+1);  35     addrSend.sin_addr.s_addr = inet_addr(IP_ADDR);  36   37     erro = bind(sockClient, (sockaddr*)&addrSend, sizeof(sockaddr));  38     if (erro == SOCKET_ERROR)  39     {  40         cout << "绑定失败!" << endl;  41         closesocket(sockClient);  42         WSACleanup();  43         return;   44     }  45   46   47 }  48   49 DWORD WINAPI RecvThread(LPVOID lParam)//接收函数  50 {  51     char buf[1024];  52     int erro;  53     int len = sizeof(addrClient);  54     while(1)  55     {  56         ZeroMemory(buf, sizeof(buf));  57         erro = recvfrom(sockClient, buf, BUF_SIZE, 0, (sockaddr*)&addrClient, &len);    58         if (erro == 0)  59         {  60             cout <<"接收失败!"<< endl;  61             return 1;  62         }  63         char * ipaddr = inet_ntoa(addrSend.sin_addr);  64         if (strcmp(buf, "") != 0)  65         {  66             cout << "服务器端" << "(" << ipaddr<< "):" << buf <<endl;  67         }  68         Sleep(50);  69     }  70   71     return 1;  72 }  73 DWORD WINAPI SendThread(LPVOID lParam)  74 {  75     char buf[1024];  76     int erro;  77     int len = sizeof(addrClient);  78     while(1)  79     {  80         ZeroMemory(buf, sizeof(buf));  81         cin.getline(buf, 1024);  82         erro = sendto(sockClient, buf, sizeof(buf), 0, (sockaddr*)&addrClient, len);    83         if (0 == erro)  84         {  85             cout<< "发送失败!"<<endl;  86             return 1;  87         }  88         Sleep(50);  89     }  90     return 1;  91 }  92 int main()  93 {  94     InitSocket();  95     CreateThread(NULL, NULL, SendThread, NULL, NULL, NULL);  96     CreateThread(NULL, NULL, RecvThread, NULL, NULL, NULL);  97     while(1)  98     {  99         Sleep(50); 100     } 101     return 1; 102 } 

    时间:2019-07-04 关键词: socket udp

  • Socket TCP 简单聊天的实现

    首先加入ws2_32.lib静态链接库:项目-属性-配置属性-链接器-输入-附加依赖项或者在声明处加入#pragma comment(lib,"ws2_32.lib")服务器端:  1 #include  客户端: 1 #include2 #include3 #include4 #include5 #include6 using namespace std;  7 SOCKET clientSocket;  8 sockaddr_in addrClient;  9 int InitSocket() 10 { 11     WSADATA wsaData; 12     int err; 13     err = WSAStartup(MAKEWORD(2,2),&wsaData); 14     if (err != 0) 15     { 16         cout<<"加载套接字库失败"<<endl; 17         return 0; 18     } 19  20     addrClient.sin_addr.s_addr = inet_addr("192.168.59.69");//=htonl(INADDR_ANY);// 21     addrClient.sin_family=AF_INET; 22     addrClient.sin_port=htons(5020); 23  24  25     clientSocket = socket(AF_INET,SOCK_STREAM,0); 26     if (clientSocket == INVALID_SOCKET) 27     { 28         cout<<"创建套接字失败!"<<endl; 29         return 0; 30     } 31     //客户端不需要绑定 32     if(connect(clientSocket,(sockaddr*)&addrClient,sizeof(addrClient)) == SOCKET_ERROR) 33     { 34         cout<<"连接服务器失败!"; 35         //如果连接成功,connect返回0;如果失败则返回SOCKET_ERROR 36         return 1; 37     } 38     return 1; 39  40 } 41 void CleanFun() 42 { 43     closesocket(clientSocket);//成功就返回0,否则返回SOCKET_ERROR。 44     WSACleanup();//解除与Socket库的绑定并且释放Socket库所占用的系统资源 45 } 46  47 //发送线程 48 UINT __stdcall SendThread(LPVOID lParam) 49 { 50     char sendBuf[65535]; 51     ZeroMemory(sendBuf,sizeof(sendBuf)); 52     while(1) 53     { 54         cin.getline(sendBuf,65535); 55         if(send(clientSocket,sendBuf,sizeof(sendBuf),0) == SOCKET_ERROR) 56         { 57             cout<<"发送失败!"; 58             return 0; 59         } 60         Sleep(50); 61     } 62     return 1; 63 } 64  65 //接收线程 66 UINT __stdcall RecvThread(LPVOID lParam) 67 { 68     while(1) 69     { 70         char szBuffer[65535]; 71         ZeroMemory(szBuffer, sizeof(szBuffer)); 72         int ret; 73         ret = recv(clientSocket,szBuffer,sizeof(szBuffer),0); 74         if(ret == 0) 75         { 76             cout<<"接收套接字失败"<0) 80         { 81             cout <<"服务器:"<< szBuffer << endl; 82         } 83         Sleep(50); 84     } 85  86     return 1; 87 } 88 int main(void) 89 {             90     InitSocket(); 91     _beginthreadex(NULL,NULL,SendThread,NULL,NULL,NULL); 92     _beginthreadex(NULL,NULL,RecvThread,NULL,NULL,NULL); 93     while(1) 94     { 95       Sleep(500); 96     } 97     CleanFun(); 98 } 

    时间:2019-06-14 关键词: tcp socket

  • UDP 通讯代码

    在使用 RAS使用拨号网络拨号的类 建立 TCP/IP后,接下来是通过 TCP/UDP 进行数据的传输。 下面是使用 UDP 的例子,分为头文件和源代码 头文件zhUDPCE.h :  源文件zhUDPCE.cpp :  使用示例: 定义  CZhUDP m_ZhUdpCE; static void CALLBACK OnZhUdpRecv(CWnd *pWnd,char *buf,int nLen,sockaddr *addr); static void CALLBACK OnZhUdpError(CWnd *pWnd,int nError);   

    时间:2019-06-14 关键词: 通讯 socket udp

  • Socket模型详解(转)

    两种I/O模式一.选择模型二.异步选择三.事件选择四.重叠I/O模型五.完成端口模型五种I/O模型的比较两种I/O模式1、两种I/O模式阻塞模式:执行I/O操作完成前会一直进行等待,不会将控制权交给程序。套接字默认为阻塞模式。可以通过多线程技术进行处理。非阻塞模式:执行I/O操作时,Winsock函数会返回并交出控制权。这种模式使用起来比较复杂,因为函数在没有运行完成就进行返回,会不断地返回WSAEWOULDBLOCK错误。但功能强大。如果你想在Windows平台上构建服务器应用,那么I/O模型是你必须考虑的。Windows操作系统提供了选择(Select)、异步选择(WSAAsyncSelect)、事件选择(WSAEventSelect)、重叠I/O(Overlapped I/O)和完成端口(Completion Port)共五种I/O模型。每一种模型均适用于一种特定的应用场景。程序员应该对自己的应用需求非常明确,而且综合考虑到程序的扩展性和可移植性等因素,作出自己的选择。我会以一个回应反射式服务器(与《Windows网络编程》第八章一样)来介绍这五种I/O模型。我们假设客户端的代码如下(为代码直观,省去所有错误检查,以下同):客户端#include#include#define SERVER_ADDRESS "137.117.2.148"#define PORT 5150#define MSGSIZE 1024#pragma comment(lib, "ws2_32.lib")int main(){WSADATA wsaData;SOCKET sClient;SOCKADDR_IN server;char szMessage[MSGSIZE];int ret;// Initialize Windows socket libraryWSAStartup(0x0202, &wsaData);// Create client socketsClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);// Connect to servermemset(&server, 0, sizeof(SOCKADDR_IN));server.sin_family = AF_INET;server.sin_addr.S_un.S_addr = inet_addr(SERVER_ADDRESS);server.sin_port = htons(PORT);connect(sClient, (struct sockaddr *)&server, sizeof(SOCKADDR_IN));while (TRUE){printf("Send:");gets(szMessage);// Send messagesend(sClient, szMessage, strlen(szMessage), 0);// Receive messageret =recv(sClient, szMessage, MSGSIZE, 0);szMessage[ret] = '';printf("Received [%d bytes]: '%s'n", ret, szMessage);}// Clean upclosesocket(sClient);WSACleanup();return 0;}客户端所做的事情相当简单,创建套接字,连接服务器,然后不停的发送和接收数据。比 较容易想到的一种服务器模型就是采用一个主线程,负责监听客户端的连接请求,当接收到某个客户端的连接请求后,创建一个专门用于和该客户端通信的套接字和 一个辅助线程。以后该客户端和服务器的交互都在这个辅助线程内完成。这种方法比较直观,程序非常简单而且可移植性好,但是不能利用平台相关的特性。例如, 如果连接数增多的时候(成千上万的连接),那么线程数成倍增长,操作系统忙于频繁的线程间切换,而且大部分线程在其生命周期内都是处于非活动状态的,这大 大浪费了系统的资源。所以,如果你已经知道你的代码只会运行在Windows平台上,建议采用Winsock I/O模型。一.选择模型Select(选择)模型是Winsock中最常见的I/O模型。之所以称其为“Select模型”,是由于它的“中心思想”便是利用select函数,实现对I/O的管理。最初设计该模型时,主要面向的是某些使用UNIX操作系统的计算机,它们采用的是Berkeley套接字方案。Select模型已集成到Winsock 1.1中,它使那些想避免在套接字调用过程中被无辜“锁定”的应用程序,采取一种有序的方式,同时进行对多个套接字的管理。由于Winsock 1.1向后兼容于Berkeley套接字实施方案,所以假如有一个Berkeley套接字应用使用了select函数,那么从理论角度讲,毋需对其进行任何修改,便可正常运行。(节选自《Windows网络编程》第八章)下面的这段程序就是利用选择模型实现的Echo服务器的代码(已经不能再精简了):Echo服务器#include#include#define PORT 5150#define MSGSIZE 1024<p style="widows: 2; text-transform: none; background-color: #ffffff; text-indent: 0px; margin: 10px auto; font: 14p

    时间:2019-06-14 关键词: socket

  • SOCKET WSAAPI socket(

    SOCKET WSAAPI socket(  int af,//协议地址族  int type,//协议套接字类型  int protocol//传输层协议);AfMeaningAF_UNSPEC0The address family is unspecified.AF_INET2The Internet Protocol version 4 (IPv4) address family.AF_NETBIOS17The NetBIOS address family. This address family is only supported if a Windows Sockets provider for NetBIOS is installed.AF_INET623The Internet Protocol version 6 (IPv6) address family.AF_IRDA26The Infrared Data Association (IrDA) address family. This address family is only supported if the computer has an infrared port and driver installed.AF_BTM32The Bluetooth address family. This address family is only supported if a Bluetooth adapter is installed on Windows Server 2003 or later.  TypeMeaningSOCK_STREAM1Provides sequenced, reliable, two-way, connection-based byte streams with an OOB data transmission mechanism. Uses the Transmission Control Protocol (TCP) for the Internet address family (AF_INET or AF_INET6).SOCK_DGRAM2Supports datagrams, which are connectionless, unreliable buffers of a fixed (typically small) maximum length. Uses the User Datagram Protocol (UDP) for the Internet address family (AF_INET or AF_INET6).SOCK_RAW3Provides a raw socket that allows an application to manipulate the next upper-layer protocol header. To manipulate the IPv4 header, the IP_HDRINCL socket option must be set on the socket. To manipulate the IPv6 header, the IPV6_HDRINCL socket option must be set on the socket.SOCK_RDM4Provides a reliable message datagram. An example of this type is the Pragmatic General Multicast (PGM) multicast protocol implementation in Windows, often referred to as reliable multicast programming.SOCK_SEQPACKET5Provides a pseudo-stream packet based on datagrams.  protocolMeaningIPPROTO_TCP6The Transmission Control Protocol (TCP). This is a possible value when the af parameter is AF_INET or AF_INET6 and the type parameter is SOCK_STREAM.IPPROTO_UDP17The User Datagram Protocol (UDP). This is a possible value when the af parameter is AF_INET or AF_INET6 and the type parameter is SOCK_DGRAM.IPPROTO_RM113The PGM protocol for reliable multicast. This is a possible value when the af parameter is AF_INET and the type parameter is SOCK_RDM. On the Windows SDK released for Windows Vista and later, this value is also called IPPROTO_PGM.  struct sockaddr {        ushort  sa_family;        char    sa_data[14];};struct sockaddr_in {        short   sin_family;        u_short sin_port;        struct  in_addr sin_addr;//把IP地址保存为4字节数        char    sin_zero[8];//填充项,使其与sockaddr结构一样长};//字节排序:主机对字节编号方式和网络不同net to host long shortntohl() ntohs()htons() htonl() sockaddr_in inter;int nport=5050;inter.sin_family=AF_INET;inter.sin_addr.s_addr=inet_addr("127.0.0.1");//IP地址→位无符长整形inter.sin_port=htons(nport);cout<<inter.sin_port;

    时间:2019-06-12 关键词: socket

  • 避免端口劫持问题,可以这么做!

    最近使用TCP server时,发现如果监控INADDR_ANY地址也就是0.0.0.0后,如果使用本机ip再去监控同样的端口,一样可以监控成功。比如我的本机地址为10.254.1.100,我监控0.0.0.0 1200端口  ,再启动一个服务器10.254.1.100 1200端口,数据都会到10.254.1.100 1200这里去,如果关闭掉10.254.1.100 1200,则数据会到0.0.0.0 1200。这个在服务器上会导致很多意想不到的结果,相当于端口被劫持了一样,并且对调试也相当不利。通过设置SO_REUSEADDR可以解决这个问题。//独占当前端口,防止多网卡情况下端口被重复使用,导致出现不可预知的情况 //不允许同一个端口在不同IP下重复监控 char opt = 0; setsockopt(sockSvr, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt)); //SO_REUSEADDR 为true 就是允许在相同的端口不同的IP地址上创建套接描述字。以下是我的多网卡测试的例子SOCKET sockSvr = WSASocket(AF_INET, SOCK_STREAM, 0, 0, 0, WSA_FLAG_OVERLAPPED); if(INVALID_SOCKET == sockSvr) { WSACleanup(); return IOCP_SOCKET_ERROR; } //独占当前端口,防止多网卡情况下端口被重复使用,导致出现不可预知的情况 //不允许同一个端口在不同IP下重复监控 char opt = 0; setsockopt(sockSvr, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt)); //SO_REUSEADDR 为true 就是允许在相同的端口不同的IP地址上创建套接描述字。 SOCKADDR_IN addrSvr; ZeroMemory(&addrSvr, sizeof(SOCKADDR_IN)); addrSvr.sin_family = AF_INET; addrSvr.sin_port = htons(port); addrSvr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); int nRet = bind(sockSvr, (SOCKADDR*)&addrSvr, sizeof(SOCKADDR)); if(SOCKET_ERROR == nRet) { WSACleanup(); return IOCP_BIND_ERROR; } nRet = listen(sockSvr, MaxListen);//500:max number of connect request if(SOCKET_ERROR == nRet) { WSACleanup(); return IOCP_LISTEN_ERROR; }不管从哪个网卡来的连接都可以接入到本端口,这样服务器就不用管当前监控的IP地址了,也不会出现端口劫持问题了。

    时间:2019-03-06 关键词: server 端口劫持 socket

  • c语言socket双向通信+一服务端对多客户端通信

    任务在完成socket客户端对服务端的通信以后,又让我搞双向通信,然后又是让我用app去控制gpio口的高低变化.努力了三天,从socket的学习到多线程的学习,一步一步的完成了任务,测试从app到服务器在到小板上的数据流全部打通.下班之前记录一下.思路socket双向通信使用的方法是服务端开启服务等客户端连接上以后开辟一个线程,然后把客户端套接字client_sockfd传递过去,输入数据后发送给客户端.反之亦然. 一服务端对多客户端的通信采用select.参考博客见:http://blog.csdn.net/ctrl_qun/article/details/52524086 作者写的非常棒,讲解的也很全面,继续研读中.对它的代码进行了部分改进.添加了对客户端上传的数据下发到所有的客户端,这个是我项目中的需求.然后添加了一个头文件.因为有些即用即初始化的参数,所以需要使用c99的标准去编译.gcc -std=c99 client.c -o client双向通信/*代码里面有部分我对驱动程序的相关控制*/ /*socket端*/ #include#include#include#include#include#include#include#include#include#include#include#define MAXBUF 512 #define DEV_IOC_MAGIC '0xee' //定义幻数 #define DEV_IOCPRINT  _IO(DEV_IOC_MAGIC, 1) #define DEV_IO_HIGH   _IO(DEV_IOC_MAGIC, 2) #define DEV_IO_LOW    _IO(DEV_IOC_MAGIC, 3) #define DEV_IOC_MAXNR 3 char send_buf[MAXBUF+1]; int fd; void *thread(void *x)   {        int cmd;     char buf[BUFSIZ];     int new_fd = *((int*)x);     while(recv(new_fd,buf,BUFSIZ,0)>0)     {         //int len=recv(new_fd,buf,BUFSIZ,0);         if(strcmp(buf,"1")==0)         {             printf("n");             cmd = DEV_IO_HIGH;             if (ioctl(fd, cmd) < 0)             {                 printf("Call cmd DEV_IO_HIGH failn");             }             printf("NOW,GPIO is High.n");         }         if(strcmp(buf,"0")==0)         {             printf("n");             cmd = DEV_IO_LOW;             if (ioctl(fd, cmd) < 0)             {                 printf("Call cmd DEV_IO_LOW failn");             }             printf("NOW,GPIO is Low.n");         }         printf("client:received:%sn",buf);     }     /*while(1)     {         bzero(send_buf, MAXBUF + 1);         scanf("%s",send_buf);         send(new_fd, send_buf, strlen(send_buf), 0); //第 4 步 向套接字中写入字符串     }*/     return NULL;   } void open_dev() {     fd = open("/dev/dsx", O_RDWR);     if(fd < 0)         printf("/dev/dsx is open fail!n"); } int main(int argc, char *argv[]) {     int client_sockfd;     int len;     struct sockaddr_in remote_addr; //服务器端网络地址结构体     char buf[BUFSIZ];  //数据传送的缓冲区     memset(&remote_addr,0,sizeof(remote_addr)); //数据初始化--清零     remote_addr.sin_family=AF_INET; //设置为IP通信     remote_addr.sin_addr.s_addr=inet_addr("0.0.0.0");//服务器IP地址     remote_addr.sin_port=htons(8000); //服务器端口号     open_dev();     /*创建客户端套接字--IPv4协议,面向连接通信,TCP协议*/     if((client_sockfd=socket(PF_INET,SOCK_STREAM,0))<0)     {         perror("socket");         return 1;     }     /*将套接字绑定到服务器的网络地址上*/     if(connect(client_sockfd,(struct sockaddr *)&remote_addr,sizeof(struct sockaddr))<0)     {         perror("connect");         return 1;     }     printf("connected to servern");     //len=recv(client_sockfd,buf,BUFSIZ,0);//接收服务器端信息     //     buf[len]='';     //printf("%s",buf); //打印服务器端信息     //新建一个线程来进行发送操作.     pthread_t ntid;     pthread_create(&ntid,NULL,thread,&client_sockfd);     /*循环的发送接收信息并打印接收信息--recv返回接收到的字节数,send返回发送的字节数*/     while(1)     {         //printf("Enter string to send:");         scanf("%s",buf);         if(!strcmp(buf,"quit"))             break;         len=send(client_sockfd,buf,strlen(buf),0);         //len=recv(client_sockfd,buf,BUFSIZ,0);         //buf[len]='';         //printf("received:%sn",buf);         printf("client:send ok.n");     }     close(client_sockfd);//关闭套接字         return 0; }/*服务端*/ #include#include#include#include#include#include#include#define MAXBUF 512 char recv_buf[MAXBUF+1]; char link_state=1; int aa; void *fun(int x) {    int new_fd=x;//(int)(*((int*)x));    while(1)    {      bzero(recv_buf, MAXBUF + 1);      scanf("%s",recv_buf);      int len = send(new_fd, recv_buf, sizeof(recv_buf) , 0);      printf("server:send okn");      if(len<=0)         break;    }     exit(0); } int main(int argc, char *argv[]) {     int server_sockfd;//服务器端套接字     int client_sockfd;//客户端套接字     int len;     struct sockaddr_in my_addr;   //服务器网络地址结构体     struct sockaddr_in remote_addr; //客户端网络地址结构体     int sin_size;     char buf[BUFSIZ];  //数据传送的缓冲区     memset(&my_addr,0,sizeof(my_addr)); //数据初始化--清零     my_addr.sin_family=AF_INET; //设置为IP通信     my_addr.sin_addr.s_addr=INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上     my_addr.sin_port=htons(8000); //服务器端口号     /*创建服务器端套接字--IPv4协议,面向连接通信,TCP协议*/     if((server_sockfd=socket(PF_INET,SOCK_STREAM,0))<0)     {           perror("socket");         return 1;     }         /*将套接字绑定到服务器的网络地址上*/     if (bind(server_sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))<0)     {         perror("bind");         return 1;     }     /*监听连接请求--监听队列长度为5*/     listen(server_sockfd,5);     sin_size=sizeof(struct sockaddr_in);     /*等待客户端连接请求到达*/     if((client_sockfd=accept(server_sockfd,(struct sockaddr *)&remote_addr,&sin_size))0)     {          printf("server:recvived:%sn",buf);     }     close(client_sockfd);     close(server_sockfd);         return 0; }一服务端对多客户端/*client端*/ #include#include#include#include#include#include#include#include#include"client_gpio.h" #define BUFFER_SIZE 1024   int main(int argc, const char * argv[])   {       struct sockaddr_in server_addr;       server_addr.sin_family = AF_INET;       server_addr.sin_port = htons(11332);       server_addr.sin_addr.s_addr = inet_addr("0.0.0.0");       bzero(&(server_addr.sin_zero), 8);       int server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);       if(server_sock_fd == -1)       {       perror("socket error");       return 1;       }       char recv_msg[BUFFER_SIZE];       char input_msg[BUFFER_SIZE];       if(connect(server_sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) == 0)       {           fd_set client_fd_set;           struct timeval tv;           open_dev();//打开驱动的设备节点.无则删除         while(1)           {               tv.tv_sec = 20;               tv.tv_usec = 0;               FD_ZERO(&client_fd_set);               FD_SET(STDIN_FILENO, &client_fd_set);               FD_SET(server_sock_fd, &client_fd_set);               select(server_sock_fd + 1, &client_fd_set, NULL, NULL, &tv);               if(FD_ISSET(STDIN_FILENO, &client_fd_set))               {                   bzero(input_msg, BUFFER_SIZE);                   fgets(input_msg, BUFFER_SIZE, stdin);                   if(send(server_sock_fd, input_msg, BUFFER_SIZE, 0) == -1)                   {                       perror("发送消息出错!n");                   }               }               if(FD_ISSET(server_sock_fd, &client_fd_set))               {                   bzero(recv_msg, BUFFER_SIZE);                   long byte_num = recv(server_sock_fd, recv_msg, BUFFER_SIZE, 0);                   if(byte_num > 0)                   {                       if(byte_num > BUFFER_SIZE)                       {                           byte_num = BUFFER_SIZE;                       }                       recv_msg[byte_num] = '';                     if(strcmp(recv_msg,"open")==0)//控制设备的相关函数,可删除                     {                         set_gpio_high();                     }                     if(strcmp(recv_msg,"close")==0)//控制设备的相关函数,可删除                     {                         set_gpio_low();                     }                       printf("服务器:%sn", recv_msg);                   }                   else if(byte_num < 0)                   {                       printf("接受消息出错!n");                   }                   else                   {                       printf("服务器端退出!n");                       exit(0);                   }               }           }         }       return 0;   }/*server端*/ #include#include#include#include#include#include#include#include#define BACKLOG 5     //完成三次握手但没有accept的队列的长度   #define CONCURRENT_MAX 8   //应用层同时可以处理的连接   #define SERVER_PORT 11332   #define BUFFER_SIZE 1024   #define QUIT_CMD ".quit"   int client_fds[CONCURRENT_MAX];   int main(int argc, const char * argv[])   {       char input_msg[BUFFER_SIZE];       char recv_msg[BUFFER_SIZE];       //本地地址       struct sockaddr_in server_addr;       server_addr.sin_family = AF_INET;       server_addr.sin_port = htons(SERVER_PORT);       server_addr.sin_addr.s_addr = inet_addr("0.0.0.0");       bzero(&(server_addr.sin_zero), 8);       //创建socket       int server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);       if(server_sock_fd == -1)       {           perror("socket error");           return 1;       }       //绑定socket       int bind_result = bind(server_sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));       if(bind_result == -1)       {           perror("bind error");           return 1;       }       //listen       if(listen(server_sock_fd, BACKLOG) == -1)       {           perror("listen error");           return 1;       }       //fd_set       fd_set server_fd_set;       int max_fd = -1;       struct timeval tv;  //超时时间设置       while(1)       {           tv.tv_sec = 20;           tv.tv_usec = 0;           FD_ZERO(&server_fd_set);           FD_SET(STDIN_FILENO, &server_fd_set);           if(max_fd<STDIN_FILENO)           {               max_fd = STDIN_FILENO;           }           //printf("STDIN_FILENO=%dn", STDIN_FILENO);       //服务器端socket           FD_SET(server_sock_fd, &server_fd_set);          // printf("server_sock_fd=%dn", server_sock_fd);           if(max_fd < server_sock_fd)           {               max_fd = server_sock_fd;           }       //客户端连接           for(int i =0; i < CONCURRENT_MAX; i++)           {               //printf("client_fds[%d]=%dn", i, client_fds[i]);               if(client_fds[i] != 0)               {                   FD_SET(client_fds[i], &server_fd_set);                   if(max_fd < client_fds[i])                   {                       max_fd = client_fds[i];                   }               }           }           int ret = select(max_fd + 1, &server_fd_set, NULL, NULL, &tv);           if(ret < 0)           {               perror("select 出错n");               continue;           }           else if(ret == 0)           {               printf("select 超时n");               continue;           }           else           {               //ret 为未状态发生变化的文件描述符的个数               if(FD_ISSET(STDIN_FILENO, &server_fd_set))               {                   printf("发送消息:n");                   bzero(input_msg, BUFFER_SIZE);                   fgets(input_msg, BUFFER_SIZE, stdin);                   //输入“.quit"则退出服务器                   if(strcmp(input_msg, QUIT_CMD) == 0)                   {                       exit(0);                   }                   for(int i = 0; i < CONCURRENT_MAX; i++)                   {                       if(client_fds[i] != 0)                       {                           printf("client_fds[%d]=%dn", i, client_fds[i]);                           send(client_fds[i], input_msg, BUFFER_SIZE, 0);                       }                   }               }               if(FD_ISSET(server_sock_fd, &server_fd_set))               {                   //有新的连接请求                   struct sockaddr_in client_address;                   socklen_t address_len;                   int client_sock_fd = accept(server_sock_fd, (struct sockaddr *)&client_address, &address_len);                   printf("new connection client_sock_fd = %dn", client_sock_fd);                   if(client_sock_fd >0)                   {                       int index = -1;                       for(int i = 0; i < CONCURRENT_MAX; i++)                       {                           if(client_fds[i] == 0)                           {                               index = i;                               client_fds[i] = client_sock_fd;                               break;                           }                       }                       if(index >= 0)                       {                           printf("新客户端(%d)加入成功 %s:%dn", index, inet_ntoa(client_address.sin_addr), ntohs(client_address.sin_port));                       }                       else                       {                           bzero(input_msg, BUFFER_SIZE);                           strcpy(input_msg, "服务器加入的客户端数达到最大值,无法加入!n");                           send(client_sock_fd, input_msg, BUFFER_SIZE, 0);                           printf("客户端连接数达到最大值,新客户端加入失败 %s:%dn", inet_ntoa(client_address.sin_addr), ntohs(client_address.sin_port));                       }                   }               }               for(int i =0; i < CONCURRENT_MAX; i++)               {                   if(client_fds[i] !=0)                   {                       if(FD_ISSET(client_fds[i], &server_fd_set))                       {                           //处理某个客户端过来的消息                           bzero(recv_msg, BUFFER_SIZE);                           long byte_num = recv(client_fds[i], recv_msg, BUFFER_SIZE, 0);                           if (byte_num > 0)                           {                               if(byte_num > BUFFER_SIZE)                               {                                   byte_num = BUFFER_SIZE;                               }                               //recv_msg[byte_num] = '';                               printf("客户端(%d):%s", i, recv_msg);                             /*转发数据给其他的客户端*/                                                      for(int i = 0; i < CONCURRENT_MAX; i++)                               {                                   if(client_fds[i] != 0)                                   {                                        send(client_fds[i], recv_msg, sizeof(recv_msg), 0);                                   }                               }                                 /*结束转发内容*/                         }                           else if(byte_num < 0)                           {                               printf("从客户端(%d)接受消息出错.n", i);                           }                           else                           {                               FD_CLR(client_fds[i], &server_fd_set);                               client_fds[i] = 0;                               printf("客户端(%d)退出了n", i);                           }                       }                   }               }           }       }       return 0;   }总结socket通信里面还有很多东西值得去研读,想想以前参加比赛的时候因为网络通信困扰了很长时间,最后还是通过别人的服务器进行操作的.现在这几天就把app到服务器在到终端打通了,虽然只是一个很简单的demo,但是别的东西无非在这基础上进行优化改进的. 继续加油,走在驱动开发的小白.

    时间:2019-01-28 关键词: C语言 socket

  • IM项目-数据库的开端

    今天开始做数据库的实验,数据库选择了mysql,这是我第一次在这一数据库下写东西,在网上找了一圈,发现原来这个东东是支持API方式访问的,随便建了个实验用工程、在包含mysql/include的头文件之后,发现编译时出现了6个错误(VC6),在网上没有找到相应的解决方案,于是决定自己找原因,发现错误都和一个叫my_socket的东东有关,于是发现一个这样的东西#ifdef __WIN__#define my_socket SOCKET#elsetypedef int my_socket;#endif /* __WIN__ */明显的,这是一个用来区别对待UNIX和WIN套接字的东西,那么根据那些错误提示,很可能是这个my_socket不知道自己应该是个什么样的东西,既然是在WIN环境下,就可以解释为SOCKET没有定义,这样一来,问题就简化了,#define my_socket SOCKET下面加上一行#include "winsock2.h"。保存再编译。通过!这个应该算是mysql自身的失误吧,许在其他win环境下的c/c++编译器下没问题,不过我没试过 差点忘了说,还要包含lib/opt下的libmySQL.lib才能编译过去

    时间:2018-11-30 关键词: 数据库 socket

首页  上一页  1 2 3 4 下一页 尾页
发布文章

技术子站