通常的网络编程socket编程。实际上。socket编程并不仅仅是满足网络间不同主机之间的通信,它也能实现同一台主机上不同进程间的通信需求。

其体如今创建socket时的參数的不同:

int socket(int domain,int type,int protocol);

对于网络间的通信,domain是AF_INET,其创建的socket须要通过IP和port来进行标识;对于同一台主机的进程间通信,其domain是AF_UNIX。其创建的socket则通过文件名称来标识。

对于网络编程刚開始学习的人而言。网络编程easy出错的地方包含下面:

1. socket有三种类型,即创建socket接口的第二个參数,         SOCK_STREAM代表TCP。即代表该socket能够像文件字节流那样操作。SOCK_DGRAM代表UDP,其是数据报文方式,在内核中抽象为类似消息队列一样管理。SOCK_RAW是原始socket类型。PING命令就是使用这样的类型。

我们在创建socket的时候一定要注意这个參数的设置。否则会出现难以捉摸的场景。刚開始学习的人往往在练习TCP编程后直接拷贝代码改为UDP进行操作,这时假设不改这个类型。那是不能调试成功的。

2. socket接口的传參问题,先来看下面接口:

l   int bind (int sockfd, struct sockaddr* addr, int addrLen);

l   int accept(int sockfd, struct sockaddr *addr, int *addrlen) ;

l   int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

l   ssize_t sendto(int socket, void *message, size_t length, int flags, struct sockaddr *dest_addr, int dest_len);

l   ssize_t recvfrom(int socket, void *buffer, size_t length, int flags, struct sockaddr *address, int  *address_len);

1)  以上接口的最后一个參数都是前一个sockaddr类型參数的字节长度。sockaddr类型參数是一个结构体,包括IP地址和PORTport。从中能够看到在addrlen在某些接口里面的传參是值传递(如bind,connect,sendto)。而在accept和recvfrom接口是地址传递。按一般的思维,地址传递是为了在接口中去改变这个地址所在的值,可是。这里的addrlen在以上接口实现中都不能被改进,它是用来告诉接口前一个參数的字节长度,所以以上全部接口在调用前这个addrlen都要被初始化。如addrlen
= sizeof(struct sockaddr), 然后再依据接口的传递要求(值传递还是地址传递)进行传參。

2)  对于str uct sockaddr* addr这个參数,接口中所有都是地址传递,但意义并不一样。

Bind接口是服务端的socket绑定自己的地址(IP和port),全部addr应该是要先初始化再传參。

Connect接口是client的socket去连接服务端,而接口中的addr就是服务端的地址。因此连接前也要进行初始化;

Sendto是UDP通信模式时源端(client/server)向对端(server/client)发送内容。因为UDP在通信前并未建立起连接,全部每次发送内容都要明白指明对端的地址,因此这个接口的addr也要先初始化再调用。

Accept是TCP模式中处于监听状态的服务端socket去接受client的连接,而这个接口的addr就是在连接成功时由系统内核调用填上client的地址信息,因此这个addr并不须要初始化;特别地,假设服务端的用户不想知道client的具体地址信息,那就传一个NULL进去,表示不care这个信息。假设accpet接口里面不想知道client的地址,那它又怎么能把数据传递回给client。那是由于accept返回的新的通信socket相应的内核数据结构已经记录到client的信息了。前面说服务端传NULL进去不care这个信息,仅仅是说用户不想得到这个信息去做某些事情,比如打印地址信息等等,但对于内核维护的socket相应的数据结构,它是一定会记录client的地址信息的。Socket提供一个接口:getpeername(conn_socket_fd,
struct sockaddr*),就行获取对端的地址信息,其跟accept接口直接获得对方的地址是等价的。

Recvfrom是UDP模式接收内容的接口。因为UDP模式在通信前不建立连接。要想在收到信息后给对方发送消息,Recvfrom收到信息时就必需要知道对端的地址。addr就是为了获取对端的地址信息的。因此其在使用前不需要初始化。

特别地,这里所讲的初始化是指初始化为有意义的地址值,如包含实际的IP和port。对于不需初始化的addr,其在传參前应该将内存清0。

3. send、recv是TCP模式的接口。因为TCP在通信前已经建立起连接,即底层的socket内核数据结构已经记录对端的地址和本段的地址信息。因此send和recv接口不需传递对端的地址信息。

sendto、recvfrom是UDP模式的接口,通信前没有建立连接。所以每次都要填上/获取对方的地址。

两种模式的发送和接收接口是一一相应的,不能混用。

因为TCP在底层数据结构中是抽象为文件字节流来操作。所以能够用一般的read和write操作,其跟recv和send是相相应的。实现相同的功能,理论上是能够相互替代的,但为了代码的可维护性,仍然要遵循相应原则。

4. connect的堵塞问题。

默认创建的socket都是堵塞的,connect也不例外,但在实践的过程中发现connect有时可以马上返回失败,并不堵塞。

其原因是:练习时往往是在虚拟机上开一个终端启动client程序,其程序中是在连接本机(127.0.0.1)的某个port,服务端未启动时,即该port并未处于监听状态,因此client的connect可以马上返回失败,即其底层可以立马得到失败的回复。堵塞的意义是一直等到有意义的应答,失败相同是一种有意义的应答,而并非说一定要等到server来连接它。

假设client程序去connect一个不存在的IP或者是经过多层路由的IP,那数据包会由于超时(IP包有一个段是标记最大存在时间的。超过这个时间的数据包会被直接丢弃)而返回,这时就行发现connect确实是堵塞的。

5. int listen (int sockfd, int backlog)
监听接口的第二个參数表示sockfd的监听队列里面最大可以存在的client连接数,有client来连接connect。那client的socket就会被加入到服务端的监听队列里面,accept接口则是服务端从监听队列里面摘走一个socket。表示接受这个client的请求。所以backlog代表服务端临时未能处理(accept)而存在于监听队列的最大连接数。

假设服务端可以及时处理accept。那随意个client都能被连接进来,当前前提是不超过linux系统的规定数。非常多人以为backlog是指最大同意这么多个客户来跟服务端通信。实际上理解错误的。可以这样做实验。服务端listen之后死循环,不再accept,看这时有多少个连接可以connect成功。

特别地,不能在同一台机启动client和服务端,由于同一台机并没有进行三次握手,connect总是可以返回成功,不受限于backlog。

版权声明:本文博主原创文章,博客,未经同意不得转载。

网络编程easy错误点-手知道的更多相关文章

  1. socket网络编程基础小记

    "一切皆Socket!" 话虽些许夸张.可是事实也是,如今的网络编程差点儿都是用的socket. --有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间怎样通 ...

  2. JAVA的网络编程

    网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者可能觉得网络编 ...

  3. JAVA网络编程【转】出处不详

    网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者可能觉得网络编 ...

  4. 【转】JAVA之网络编程

    转自:火之光 网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者 ...

  5. C# 网络编程之豆瓣OAuth2.0认证具体解释和遇到的各种问题及解决

            近期在帮人弄一个豆瓣API应用,在豆瓣的OAuth2.0认证过程中遇到了各种问题,同一时候自己须要一个个的尝试与解决,终于完毕了豆瓣API的訪问.作者这里就不再吐槽豆瓣的认证文档了,毕 ...

  6. 完毕port(CompletionPort)具体解释 - 手把手教你玩转网络编程系列之三

       手把手叫你玩转网络编程系列之三    完毕port(Completion Port)具体解释                                                    ...

  7. JAVA的网络编程【转】

    JAVA的网络编程[转] Posted on 2009-12-03 18:04 火之光 阅读(93441) 评论(20) 编辑 收藏 网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能, ...

  8. C/C++ 用libcurl库进行http通讯网络编程

    C/C++ 用libcurl库进行http通讯网络编程 目录索引: 一.LibCurl基本编程框架 二.一些基本的函数 三.curl_easy_setopt函数部分选项介绍 四.curl_easy_p ...

  9. Java学习之网络编程实例

    转自:http://www.cnblogs.com/springcsc/archive/2009/12/03/1616413.html 多谢分享 网络编程 网络编程对于很多的初学者来说,都是很向往的一 ...

随机推荐

  1. 【Android进阶】Android面试题目整理与讲解(一)

    这一篇文章专门整理一下研究过的Android面试题,内容会随着学习不断的增加,如果答案有错误,希望大家可以指正 1.简述Activity的生命周期 当Activity开始启动的时候,首先调用onCre ...

  2. UVa 825 - Walking on the Safe Side

    题目:在一个N*M的网格中,从左上角走到右下角,有一些点不能经过,求最短路的条数. 分析:dp,帕斯卡三角.每一个点最短的就是走N条向下,M条向右的路. 到达每一个点的路径条数为左边和上面的路径之和. ...

  3. Android.mk参数解释

    -------------------- 下面对Android.mk 中经常出现的变量进行讲解 -------------------- 这些变量,你会经常在Android.mk文件中见到,下面以字表 ...

  4. 【SICP读书笔记(三)】练习2.18 --- 表序列的reverse方法

    来自练习2.18 请定义出过程reverse,它以一个表为参数,返回的表中所包含的元素与参数表相同,但排列顺序与参数表相反: (reverse (list 1 4 9 16 25)) (25 16 9 ...

  5. 理解和运用javascript中的call及apply

    call是为了改变函数上下文context而存在的,换言之,就是改变函数内部this的指向.因为javascript存在[定义时上下文],[运行时上下文]及[上下文]是可以改变的.例如:var fun ...

  6. android对app代码混淆

    接到新任务.现有项目的代码混淆.在此之前混淆了一些理解,但还不够具体和全面,我知道有些东西混起来相当棘手. 但幸运的是,现在这个项目是不是太复杂(对于这有些混乱).提前完成--这是总结. 第一部分 介 ...

  7. SRM 628 D1L3:DoraemonPuzzleGame,math,后市展望,dp

    称号:c=problem_statement&pm=13283&rd=16009">http://community.topcoder.com/stat?c=probl ...

  8. PC2日记——坑爹的第一天2014/08/28

    我不想安慰自己说今天是因为第一次将pc2用于实际的比赛经验不足而导致的今天出现种种问题,我想说的是自从我開始干后台我所做的每一件事都是第一次,所以这绝对不是让自己免去责怪的理由:我想说的是假设我今天是 ...

  9. 返璞归真 asp.net mvc (1) - 添加、查询、更新和删除的 Demo

    原文:返璞归真 asp.net mvc (1) - 添加.查询.更新和删除的 Demo [索引页] [源码下载] 返璞归真 asp.net mvc (1) - 添加.查询.更新和删除的 Demo 作者 ...

  10. HttpLuaModule——翻译(Nginx API for Lua) (转)

    现在我已经将翻译的内容放到:http://wiki.nginx.org/HttpLuaModuleZh Nginx API for Lua Introduction 各种各样的*_by_lua和*_b ...