网络通信编程
文章平均质量分 92
全面介绍网络编程的知识,包括socket服务器/客户端的编写、网络编程里面的多线程、多进程、IO复用技术等等。
HymanLiuTS
年过而立,又酸又臭,忙时敲代码,闲时读书写文章。
展开
-
网络编程(58)—— Windows下使用CSocket搭建回声服务端和客户端
CSocket是对CAsyncSocket的一个再次封装,它将CAsyncSocket这种异步不阻塞的socket封装成了同步阻塞的socket。它的实现原理其实很简单,我们应该留意到在CAsyncSocket中Accept、Send、Receive函数被定义成了虚函数:virtual BOOL Accept( CAsyncSocket& rConnectedSocket, SOCKADDR*原创 2017-01-11 22:38:25 · 2061 阅读 · 0 评论 -
网络编程(57)—— Windows下使用CAsyncSocket搭建回声服务端和客户端
一、 引言 CAsyncSocket是MFC中对WSAAsyncSelect异步非阻塞通知IO的一个封装类。我们在《Windows下使用WSAAsyncSelect实现窗口处理socket消息》一文中讨论过WSAAsyncSelect的用法,知道它绑定一个窗口到一个socket,并注册了我们自定义的消息和需要监视的IO事件类型(FD_ACCEPT、FD_READ、FD_WRITE原创 2017-01-11 22:32:58 · 2253 阅读 · 0 评论 -
网络编程(56)—— Windows下使用IOCP构建socket服务端
一、完成端口对象 不同于IO重叠对象在IO完成时通过触发事件或者触发CompletionRoutine回调函数,IOCP模型将socket和完成端口对象(CompletionPort,简称CP对象)绑定,当IO操作完成时,会改变该对象的状态,而我们通过完成端口对象,便可以确认IO操作是否完成。 创建完成端口对象的API如下:HANDLE WINAPI Crea原创 2017-01-10 15:20:49 · 2461 阅读 · 0 评论 -
网络编程(55)—— Windows下使用WSASocket基于Completion Routine进行IO重叠
一、引言 上一文中我们介绍了使用基于事件进行IO重叠的方法,本文主要介绍另外一种,基于回调函数void CALLBACK CompletionRoutine(DWORD dwError,DWORDszRecvBytes,LPWSAOVERLAPPED lpOverlapped,DWORD flags)进行IO重叠。首先,我们先介绍一种线程的状态——alertable wait状态原创 2017-01-09 14:03:55 · 2600 阅读 · 0 评论 -
网络编程(54)—— Windows下使用WSASocket基于事件进行IO重叠
一、引言 本文主要研究下Windows下的IO重叠技术。 何为IO重叠?按照它的定义,在同一个线程中,我们同时向多个目标socket发送数据或者从多个socket接收数据,而我们用于传递和接收的函数未等IO过程结束就返回,而数据的传递和接收工作完全交给了操作系统,在这个过程中针对目标socket的每个IO操作在时间片上都发生了重叠,这就是IO重叠,如下图所示:原创 2017-01-06 08:27:48 · 2390 阅读 · 0 评论 -
网络编程(53)—— Windows下使用WSAAsyncSelect实现窗口处理socket消息
一、引言 上一文中我们介绍了使用WSAEventSelect实现异步通知IO的方法,本文我们主要讨论下使用WSAAsyncSelect处理socket的方法。本文的主要目标,是创建一个带界面的回声服务端,接收并返回客户端传过来的字符串,并在界面上显示该字符串。为此,我们将采用MFC的编程环境,建立如下的对话框程序:二、WSAAsyncSelect函数原创 2017-01-05 08:23:08 · 3165 阅读 · 0 评论 -
网络编程(52)—— Windows下使用WSAEventSelect实现异步通知IO
一、同步IO和异步IO 同步IO是指发生IO事件的时间点和相关函数返回的时间点一致。如使用send函数发送数据时,所有的数据发送到输出缓冲区后,send函数才会返回,这种IO方式就是同步IO。异步IO指函数先于IO事件返回。还是以send函数为例,调用send函数后其马上返回,而数据传送到输出缓冲区交给操作系统完成。这种IO方式就是同步IO。 什么是异步IO通知原创 2017-01-04 09:02:52 · 1283 阅读 · 0 评论 -
网络编程(51)—— Windows下使用select进行IO复用
本文主要介绍在Windows系统下使用select搭建回声服务端的方法。在之前的《网络编程(16)—— IO复用技术之select》一文中我们介绍了在Linux使用Select进行IO复用的方法。本文对其原理不再详述,旨在通过对比使用加强对select的理解和应用。整个Windows版的select服务端的代码如下,稍后我们将对关键代码进行解释。// SelectServ.cpp : 定义控制原创 2017-01-03 08:40:20 · 4603 阅读 · 1 评论 -
网络编程(50)—— 使用poll搭建回声服务端
一、 引言 本文主要介绍在linux中使用poll搭建回射服务端。我们在前面的文章中研究了使用select和epoll搭建服务端的方法。poll的用法和select类似,只不过用来描述操作符集合的是pollfd而非select的fd_set。Poll在Linux 2.5.44版本后被epoll取代,本文只为研究其用法。二、函数原型poll的函数原型如下:#includ原创 2016-12-31 12:14:53 · 1346 阅读 · 0 评论 -
网络编程(49)—— epoll的条件触发和边缘触发
一、条件触发和边缘触发 在《网络编程(21)—— 使用epoll进行IO复用》一文中,我们介绍了在linux平台下使用epoll进行IO复用的方法。本文主要介绍epoll中进行IO复用的两种触发方式:条件触发和边缘触发。1.1 什么是条件触发和边缘触发? epoll进行IO复用的基本原理我们可以概括如下:1、 使用epoll_create()创建用来保存e原创 2016-12-30 17:15:42 · 3480 阅读 · 3 评论 -
网络编程(48)—— windows平台下的四种线程同步技术(二)
四、内核同步对象—— 互斥(Mutex) 内核线程同步对象包括互斥、信号量和事件,它们使用时存在很多共通之处。下面先介绍在Windows平台利用互斥进行线程的同步。HANDLE WINAPI CreateMutex(__in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes,__in BOOL bInitialOwner,__in_原创 2016-12-29 08:16:46 · 1108 阅读 · 0 评论 -
网络编程(47)—— windows平台下的四种线程同步技术(一)
一、用户模式和内核模式 Windows操作系统在运行时,存在以下两种模式:用户模式:是运行应用程序的基本模式,不能访问硬件,且访问的内存的范围也有限制。内核模式:是操作系统运行的基本模式,可以访问硬件,访问的内存范围无限制。 Windows的程序在运行时,往往频繁的在用户模式和内核模式之间切换。以多线程程序为例,我们所创建的线程属于操作系统,在创建线原创 2016-12-28 09:01:31 · 1472 阅读 · 0 评论 -
网络编程(46)—— windows内核对象的两种状态
一、 什么是内核对象? 我们知道进程、线程、文件、互斥、信号量这些都是操作系统级别的资源。我们在使用这些资源时,实际上都是由操作系统进行创建和管理的。操作系统为了管理这些资源,会在其内部创建一个数据块,也可以理解为一个结构体对象。这个数据块就是内核对象。二、 内核对象有哪两种状态? 内核对象的状态共有两种:signaled(有信号)状态和non-sign原创 2016-12-27 08:52:05 · 1832 阅读 · 0 评论 -
网络编程(45)—— windows平台下销毁线程的四种方法
原文出自:http://www.cnblogs.com/goalone1985/articles/2126420.html终止线程运行 若要终止线程的运行,可以使用下面的方法: • 线程函数返回(最好使用这种方法)。 • 通过调用 ExitThread 函数,线程将自行撤消(最好不要使用这种方法)。 • 同一个进程或另一个进程中的线程调用 TerminateThre转载 2016-12-26 08:46:42 · 2504 阅读 · 0 评论 -
网络编程(44)—— windows平台下创建线程的四种方法(三) 工作者线程和CWinThread线程类管理
四、AfxBeginThread4.2 工作者线程 工作者线程类似我们之前介绍的用CreateThread创建的线程,它在后台处理数据,和主界面线程共享消息循环。它用AfxBeginThread的重载版本创建,函数原型如下:CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pPar原创 2016-12-23 08:37:51 · 4358 阅读 · 0 评论 -
网络编程(43)—— windows平台下创建线程的四种方法(二)之用户界面线程
四、AfxBeginThread 在介绍使用AfxBeginThread进行多线程编程之前,我们先介绍下MFC中两种线程的概念,这也是在MFC编程中无法绕过的两种类型的线程 —— 用户界面线程和工作者线程。4.1 用户界面线程 用户界面线程,顾名思义,它是一种可以管理UI界面的线程。它含有自己的消息循环,可以处理UI界面的各种消息。最常见的用户界面线程,就是原创 2016-12-22 08:47:57 · 1568 阅读 · 0 评论 -
网络编程(42)—— windows平台下创建线程的四种方法(一)
一、引言 接下来,笔者主要谈下Windows平台下多线程的用法。首先,要强调一点,Windows平台的线程linux中的线程不同,它会伴着主函数的结束而销毁。Windows平台下可用的创建多线程的API共有四个,分别是:(1) CreateThread() CreateThread是Windows的API函数,提供操作系统级别的创建线程的操作,且仅限于工作者线原创 2016-12-21 08:11:28 · 1876 阅读 · 0 评论 -
网络编程(41)—— Linux线程销毁的两种方法
Linux的线程的创建必然会伴随着内存空间的分配,而当线程函数执行完毕时,线程空间同样也不会被自动收回。特别是,Linux线程的销毁和进程也不一样,即使主函数结束,如果不主动回收,线程空间也不会被释放。类似于永远不能被回收的僵尸进程,我们姑且叫这种线程为僵尸线程吧。本文就是介绍回收这种僵尸线程的资源的两种方法。方法一:利用pthread_join()函数。 这个函数在原创 2016-12-19 12:52:02 · 6514 阅读 · 1 评论 -
网络编程(40)—— 使用信号量semaphore进行多进程间的同步
本文主要介绍下在多进程中使用信号量semaphore的方法。在上一文中,我们已经知道semaphore和mutex对临界区访问控制的一个最主要区别就是semaphore可以跨进程使用,而mutex只能在一个进程中使用。我们再来看下sem_init的原型,熟悉决定进程共享或者线程共享的方法:#include int sem_init(sem_t *sem, int pshared, unsig原创 2016-12-18 14:20:40 · 7349 阅读 · 5 评论 -
网络编程(39)—— 使用信号量semaphore进行多线程同步
一、Semaphore相关函数 之前介绍过了多线程中利用互斥mutex控制多线程中对临界区的访问方法,本文主要介绍下利用信号量semaphore控制线程对临界区的访问。首先,我们先看一下semaphore相关的函数:1.1 头文件#include 与之前互斥mutex所引用的头文件pthread.h不同,semaphore的相关函数在semaphore.原创 2016-12-17 11:26:56 · 1973 阅读 · 0 评论 -
网络编程(38)—— 利用互斥mutex控制多线程对临界区的访问
解决多线程访问临界区的冲突问题,最常用的方法就是利用互斥量mutex了。linux中互斥的使用分为以下步骤:1、定义互斥量。pthread_mutex_t mutex; 互斥量的本质其实就是一个结构体,请参照/usr/include/bits/pthreadtypes.h中对pthread_mutex_t的定义:typedef union{ struct _原创 2016-12-16 08:43:37 · 1591 阅读 · 0 评论 -
网络编程(37)—— 线程访问的临界区是怎么形成的
本文主要讨论多线程访问中临界区形成的问题,从本质上讲,临界区的形成是在多线程中,不同的线程访问和操作同一片内存,而形成的。在具体分析之前,我们先来看一个多线程的列子:#include#includeint num=0;void* pthread_main1(){ int i=0; for(i=0;i<1000000000;i++) { num+原创 2016-12-15 08:58:23 · 1273 阅读 · 0 评论 -
网络编程(36)—— 线程安全函数和非线程安全函数
今天研究下线程安全函数和非线程安全函数。什么是线程安全函数?我们知道在多线程编程中,线程安全问题是不容忽视的。只要存在多线程,就会存在多个线程访问同一段代码或者同一个全局变量的临界区,对于uc中标准函数也是一样(类似于windows中的原子函数)。当多个线程同时调用一个标准函数时,执行同一段代码,同样会在函数内部形成临界区,就可能出现问题。 线程安全函数就是针对上述问题,在函数内原创 2016-12-14 08:40:23 · 2870 阅读 · 0 评论 -
网络编程(35)—— 利用pthread_join函数等待线程结束并获取线程函数返回值
在linux中的多线程一节中,我们介绍了利用pthread_create()函数创建子线程的方法。这种方式创建的线程存在一个问题:在主线程创建完成子线程后,若子线程函数还没结束时,但是此时主线程函数已经结束,那么子线程也会被强制销毁,为了避免这个问题,当时我们在主线程中sleep了11秒钟以等待子线程的结束。虽然暂时避免了问题的发生,但是显然这不是很友好的解决方案,因为在实际编程中你无法预料子原创 2016-12-13 09:30:05 · 6956 阅读 · 0 评论 -
网络编程(34)—— linux中的多线程
本文主要研究下linux中多线程的用法。 在之前的几篇文章中,介绍过Linux中多进程的实现,现在我们开始研究下linux中的多线程。之前曾经实现过多进程的linux服务器,解决了多客户端连接时的效率问题,但是它还存在以下问题:1、创建子进程时,需要完全复制父进程的内存,造成很大的性能开销。2、由于各个进程之间不属于同一片内存,进程间通信需要特殊的IPC技术3、CPU原创 2016-12-12 08:49:20 · 754 阅读 · 0 评论 -
网络编程(33)—— 使用AF_UNIX构建本地通信的socket服务端和客户端
之前一直使用AF_INET构造socket服务端和客户端,本文介绍下使用AF_UNIX构建本地通信的socket服务端和客户端。我们先列出代码,然后在对代码进行分析:服务端:#include#include#include#include<sys/socket.h#include#include//头文件发生了变化#define BUF_SIZE 1024 void e原创 2016-12-09 08:12:36 · 3213 阅读 · 0 评论 -
网络编程(32)—— linux中销毁僵尸进程的四种方法
一、wait函数函数原型:pid_t wait(int *status);描述:wait可以回收任意一个僵尸进程,只要系统中存在僵尸进程,调用一次wait,就会回收一个僵尸进程。参数说明: status - 当子进程结束之后,其进入僵尸进程状态。其状态变化信息被操作系统放置在内存中某一处位置,而status就是这处位置的指针,通过调用wait函数可以获取这部分位置原创 2016-12-08 08:03:15 · 3825 阅读 · 0 评论 -
网络编程(31)—— 路由控制原理
一、数据包的路由控制 一个IP数据包,从一台主机到达另一台主机,中间往往需要经过多个数据链路以及路由器。而中间的一个路由器,往往通过接口和多个路由器或者主机相连,我们知道IP数据包的首部包含该包的源地址和目标地址,当IP数据包到达该路由器时,路由器有怎么知道把这个包发到哪个接口相连的路由器或者主机呢? 这就需要路由控制表了,所谓路由控制表其实就是就是与本主机或者路原创 2016-11-05 07:46:20 · 1446 阅读 · 0 评论 -
网络编程(30)—— IP地址分类和子网掩码的作用
一直以来对于IP地址的分类和子网掩码的作用比较模糊,总是感觉似懂非懂,现在主要将其进行整理,抛开一些很深邃的技术概念,单纯对基本知识进行整理。 一、IP地址的分类: 目前IP地址被分为A、B、C、D、E五种类型,下面分别对五种类型的分类标准进行介绍: A类地址: 该类地址转换成二进制以0开头,前8位表示网络地址,后面24位表示主原创 2016-11-01 00:18:42 · 2393 阅读 · 0 评论 -
网络编程(29)—— socket的close函数以及shutdown函数在多进程服务器中的不同表现(二)
本文紧接着上一遍文章《socket的close函数以及shutdown函数在多进程服务器中的不同表现(一)》,来验证上文中提到的几个结论:1、 复制后的socket描述符真的指向同一个socket吗? 为了验证这个问题,我们先创建一个socket,然后复制一份改socket描述符的副本,再分别打印这两个socket描述符,若描述符打印结果一致,说明指向同一个socket。int原创 2016-12-07 00:21:37 · 1281 阅读 · 0 评论 -
网络编程(28)—— socket的close函数以及shutdown函数在多进程服务器中的不同表现(一)
这几天遇到了一个很奇怪的问题,编写了一个读写IO分离的多进程socket客户端,主要功能是在成功connect服务端后,fork一个子进程,在子进程中不断的提示用户输入字符串(输入Q或者q会退出程序),然后发给服务端。然后再父进程中不断的读,读取从客户端发送过来的数据。代码如下:#include#include#include#include#include#include#inc原创 2016-12-06 20:35:26 · 1762 阅读 · 0 评论 -
网络编程(27)—— 再谈Nagle算法
这段时间一直在研究Nagle算法问题,其实自从了解到这个算法以后,心里有不少的疑问,本文主要是对我自己这些疑问的一个分析,属于个人的一个理解,如果有哪个大神一不小心路过这里,有错误的地方还望给予批评教育~~ 问题一,Nagle算法是不是TCP可靠连接的基础,把Nagle算法禁用了是不是TCP就变成不可靠连接了? 先说答案,答案是否定的。Nagle只是一个算法而已,TCP是可原创 2016-11-08 19:04:48 · 1170 阅读 · 0 评论 -
网络编程(26)—— TIME_WAIT、FIN_WAIT1、FIN_WAIT2和CLOSE_WAIT状态的区别
下面接着《详解TCPIP断开连接后的Time-wait状态》一文的内容,我们讨论下socket在断开连接中的另外三种状态FIN_WAIT1、FIN_WAIT2状态和CLOSE_WAIT状态。首先启动socket服务端,然后用客户端进行连接,用netstat –ant命令查看目前套接字的状态: 发现客户端和服务器的套接字都进入了established状态,说明客户端和服务端都原创 2016-11-07 19:47:48 · 15887 阅读 · 2 评论 -
网络编程(25)—— 详解TCPIP断开连接后的Time-wait状态
之前在《socket选项之SO_REUSEADDR和TCP_NODELAY》一文中简单介绍过断开连接的一方套接字进入的Time-wait状态。现在我们详细的讨论该状态,以解决下面疑问: 1、 Time-wait状态是怎么产生的?2、客户端在断开连接后会进入Time-wait状态吗?3、Time-wait状态有什么用?4、Time-wait状态下的端口号能否设置被其他套原创 2016-11-06 18:00:14 · 4653 阅读 · 2 评论 -
网络编程(24)—— linux中write和read函数的阻塞试验
刚刚接触网络编程时,很容易被客户端和服务器之间的交互搞晕,例如各种函数的阻塞和非阻塞就让人头疼。例如在我的印象中linux中用于用于对文件描述符进行读写的write()函数和read()函数是非阻塞函数,但是在一次网络通信的试验中发现它们又是阻塞的,后来man了一下write和read,发现其文档中都有下面一句话:ERRORS EAGAIN The file descr原创 2016-10-31 08:15:39 · 8334 阅读 · 4 评论 -
网络编程(23)—— socket客户端连接上服务端是在listen之后而非在accept之时
我们知道在TCPIP中客户端同服务端建立连接,需要三次握手: 第一次:客户端向服务端请求发起连接,发送SYN 第二次:服务端收到客户端的请求后,向客户端回送ACK和SYN 第三次:客户端接收到服务端可以连接的信息,再向服务端发送ACK,表示收到服务端信息完成连接。 在刚刚接触网络编程时,很长一段时间都以为只有服务端调用accept后,客户端才会connect成功,但原创 2016-10-27 17:37:57 · 3719 阅读 · 0 评论 -
网络编程(22)—— socket客户端和服务端收发数据包需要一对一的关系吗?
其实这个题目应该是一个疑问句,接触了这么久的TCPIP网络编程,一直不敢确定是不是在客户端和服务端分别进行读和写时,write和read要成对出现?我想这也是很多网络编程的新手存在的疑问吧。 下面,就针对这个问题进行试验,以解答长久以来的疑惑。 我们写这样一个服务端,每当接收到客户端的数据是重复发送三次,发回给客户端。#include#include#inclu原创 2016-10-25 14:03:02 · 3563 阅读 · 0 评论 -
网络编程(21)—— 使用epoll进行IO复用
之前介绍了用于IO复用的select函数,其基本原理就是先在select函数中注册需要进行监视的条件操作符的集合,每次调用select,若集合中某个文件操作符存在待读数据、可传输无阻塞数据、或者异常时,改文件操作符在集合中被保留,其他被清零。 利用select进行IO复用,适合比较少连接或者有跨平台需求的服务器的开发,因为有两处制约其在处理多连接时的性能: 1、每次都需要将包含文件操作原创 2016-10-24 17:37:11 · 1282 阅读 · 0 评论 -
网络编程(20)—— 广播的编程实现
一、广播和多播的区别 多播和广播的范围有区别,多播即使在跨越不同网络的情况下,只要加入多播组就能接受数据。而广播只能向同一网络中的主机传输数据。二、广播的分类 广播分为两种,直接广播和本地广播。二者的主要差别在于IP地址,直接广播的IP地址,除了网络地址外,其余主机地址全部设置为1.如希望向网络地址192.12.34的所有主机传输数据时,可以向192.12.34.2原创 2016-10-23 08:53:48 · 4233 阅读 · 1 评论 -
网络编程(19)—— 多播的编程实现
多播,使用UDP协议传递数据的一种方式,发送数据的主机向一个计算机组发送数据,所有注册在该计算机组中的计算机都能接受到该数据。在网络层,一般通过路由器可实现该功能。首先,发送数据的主机发送一组数据,然后到达支持多播功能的路由器后,路由器会进行复制,将数据包复制后发给本组的其他计算机。 在软件中实现多播,需要将目标地址设置成任意D类ip地址(224.0.0.0~239.255.255.2原创 2016-10-16 10:19:40 · 2572 阅读 · 2 评论