<转>Socket编程——基础介绍
最近系统的看了下unix网络编程的一些内容,对socket的理解有了进一步的加深,在看APUE的时候,那会儿看socket上面介绍的比较少,只是模糊的懂了如何去写一个简单的TCP服务端和客户端,对其中一些注意的点,以及实现的原理没有过多的去研究。这是我自己总结的socket编程的第一篇,基本就是介绍一些基础性的东西。
这个只是在IPV4上的一些socket编程,对于IPV6暂不涉及。下面对unix网络编程卷一第三版简称为unpV13e
地址结构
提到地址结构我们一般使用的是最基本的地址结构。IPV4的地址结构为struct sockaddr_in 里面包含了一些字段。如sin_family, sin_addr, sin_port.对于sin_addr这是一个结构体类型的。声明是struct in_addr.struct sockaddr_in是定义在<netinet/in.h>中的。而对于结构体中所 涉及到的变量的定义一般包含在<sys/types.h>, <sys/socket.h>. 所以一般在编程的时候需要注意将这些头文件引用。
上述详细的讨论可以参看UnpV13e的p56-p57。里面的讨论比较详尽。
接着我们还有一类地址结构,称作通用地址结构。这是地址结构的引入是为了对各种socket的地址结构做一个统一的,通用地址的定义是struct sockaddr 舍去了后缀。这个地址结构的使用我们一般是用在类型强转上面。例如bind函数第二个参数需要强转为struct sockaddr 遵循Richard的思想,将struct sockaddr精简一下,使用define将其定义为SA. 如此便省去敲击的次数。
最后还有一类更加通用的地址结构,称作新的通用地址结构. 它比之前的地址结构更具通用性,能够存储任意大小的结构体。struct sockaddr_storage这个结构一部分是对用户透明的。所以使用的时候我们一般不需要担心空间不够。
字节序
不同的机器上,使用的字节序一般是不同的,一般称作大端和小端。我们为什么要讨论这个问题呢?因为作为网络编程,双方之间的通信要一致。比如我这边是使用的小端,而对方机器是大端,那么解析后的结果就是错乱的,因此我们需要做的就是将其统一起来。需要一个能够将本地转为网络字节,再从网络字节转为本地,这之间的细节包括网络字节转本地的时候需要对机器进行大小端的判断。这样就避免了错乱。我们自己如何来判断一个机器的大小端呢?
我们使用的是联合这个数据类型来实现的。具体的实现参看我的Gits,一般linux上使用的是小端字节序。
讨论了字节序后我们需要知道的是如何将本地和网络字节序进行互换,一般提供了一些接口,我们一一来简单的讨论下。
TCP中一般是16位的端口号和32位的IPV4地址。而我们在实现本地转网络的时候不需要去考虑本地是大端还是小端了,只需要考虑需要转的内容长度了。因为从如下的四个函数可以看出htons,htonl,ntohs,ntohl 这边的n代表network,h代表host, l代表long,s代表short。我们把l视为32位的,将s视为16位的。这样在转换ip和port的时候就很方便了。但是需要注意的就是我们在使用这些函数的时候需要注意的就是我们的参数是整型的,这一点需要注意到。
字节操纵函数
对一个结构体进行初始化,或是数组初始话的时候我们要做的就是使用一些字节操纵函数来实现。一般我们会想到使用memset这个函数,同样在linux中有另外一组不错的函数,是BSD所提供的,称作bzero bcmp bcopy 以字节来实现相关的操作,而不是以c语言中string的这个概念中所做的那样。
使用bzero在网络编程中是又好处的。因为参数少,直接将目标初始化成0. 而memset多一个参数。还有一点就是memset无法处理字节重叠的这个问题。而bzero是可以解决的。这一块使用bzero可以省去一些麻烦。这个函数是包含在<strings.h>这个头文件中的。而memset是包含在<string.h>中的。
字符串处理的函数
一般我们的输入都是基于字符串这个格式的,使用的比较多,所以如果提供一个直接将字符串格式的地址或是端口转换成网络字节序的函数的话,那么我们就会变得更加的方便。
这边也有两组不一样的函数,一般我们倾向使用后面一组。 好了先说说第一组的函数。
- inet_aton ====> 将点分十进制的内容转换成网络字节序,参数是两个,一个是strptr,另一个是地址addrptr。详情参看手册页。
- inet_addr ====> 几乎淘汰,有一些弊端
- inet_ntoa ====> 将网络字节序的转换为本地的字符串格式。 参数只有一个。
这组函数用起来还是可以的。不过更流行的使用是使用下面的这两个。
- inet_pton ====> 将本地的字符串的描述转为网络字节序,参数有三个。
- inet_ntop ====> 将网络字节序的转为本地的字符串形式。参数有四个。
不过为了防止错误,在<netinet/in.h>中有一个好的定义,为INET_ADDRSTRLEN 大小定义为16,这就保证了我们的大小不会溢出。
上面的两组函数都包含在<arpa/inet.h>这个头文件中。
但是下面的那两个函数有一个不太好的就是我们要确定sock的类型,而不是直接传入一个地址结构,所以Richard给出了这样的一个封装函数,处理起来应该就是比较轻松一些。
char *sock_ntop(const sockaddr *sa, socklen_t salen)
{
char portstr[];
static char str[]; //unix domain is largest switch(sa->sin_family)
{
case AF_INET:
{
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
if(inet_ntop(AF_INET,&sin->sin_addr,str,sizeof(str)) == NULL)
return NULL;
if(ntohs(sin->sin_port) != )
{
snprintf(portstr,sizeof(portstr),":%d",ntohs(sin->sin_port));
strcat(str,portstr);
}
return str;
}
}
}
另外还有其他几个函数,实现都可以在源代码中找到。因为这些函数比较好的一个点就是我们调用的时候省去了很多的细节。
socket的一部分内容基本上是介绍完了。在字节流套接字上,read和write是不同于文件的I/O的。所以还有一套不错的函数
- readn
- written
- readline
这三个函数会在下一篇中给出,下一篇将这些函数实现。并且又另一个版本的叫RIO。虽然如出一辙,但是还有一些更加不错的函数提供出来。这对 网络编程中I/O提供的一个好的解决。
<转>Socket编程——基础介绍的更多相关文章
- socket编程基础-字节序/IP/PORT转换/域名
socket编程基础 网络IP操作函数 字符串的IP和32位的IP转换 #include <sys/socket.h> #inlcude <netinet/in.h> #inc ...
- shell脚本编程基础介绍
Linux系统——shell脚本编程基础介绍 1.什么是shell 它是一个命令解释器,在linux/unix操作系统的最外层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种操作输出的结果 ...
- c#socket编程基础
Microsoft.Net Framework为应用程序访问Internet提供了分层的.可扩展的以及受管辖的网络服务,其名字空间System.Net和System.Net.Sockets包含丰富的类 ...
- 【转】Java Socket编程基础及深入讲解
原文:https://www.cnblogs.com/yiwangzhibujian/p/7107785.html#q2.3.3 Socket是Java网络编程的基础,了解还是有好处的, 这篇文章主要 ...
- 【Socket】Java Socket编程基础及深入讲解
Socket是Java网络编程的基础,了解还是有好处的, 这篇文章主要讲解Socket的基础编程.Socket用在哪呢,主要用在进程间,网络间通信.本篇比较长,特别做了个目录: 一.Socket通信基 ...
- 你得学会并且学得会的Socket编程基础知识
这一篇文章,我将图文并茂地介绍Socket编程的基础知识,我相信,如果你按照步骤做完实验,一定可以对Socket编程有更好地理解. 本文源代码,可以通过这里下载 http://files.cnblog ...
- Java从零开始学四十五(Socket编程基础)
一.网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可 ...
- java socket编程基础(转)
一,网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可 ...
- Python学习笔记——基础篇【第七周】———FTP作业(面向对象编程进阶 & Socket编程基础)
FTP作业 本节内容: 面向对象高级语法部分 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 参考:http://www.cnblogs.com/wupeiqi/ ...
随机推荐
- 结构体、枚举、联合(day14)
一个存储区的地址必须是它自身大小的整数倍 (double类型存储区的地址只需要是4的 整数倍) 这个规则叫数据对齐 结构体里面的子存储区通常也需要遵守数据 对齐的规则 数据对齐会造成结构体内部子存储区 ...
- [luogu2054 AHOI2005] 洗牌 (数论)
传送门 Solution 我们考虑每一步牌的变化: 前半部分的牌位置*2 后半部分的牌位置*2-n-1 那么我们可以看做是\(x\times 2^m\equiv l \pmod n\) 于是求个逆元就 ...
- em与当前元素的不解之缘
em是相对于当前元素的字体大小而言,比如font-size:14px;那么这个元素的1em=14px. 如果当前元素未定义字体大小,则会向上继承父元素的字体大小,如果当前元素的所有祖先元素都没有定义f ...
- 2-SAT·hihoCoder音乐节
2-SAT·hihoCoder音乐节 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 hihoCoder音乐节由hihoCoder赞助商大力主办,邀请了众多嘉宾和知名乐队 ...
- elasticsearch Suggester实现搜索建议(八)
Completion Suggester 智能提示 { "settings": { }, "mappings": { "doc": { &q ...
- UDP bind() IP和prot
http://blog.csdn.net/qq_28171461/article/details/69523604
- [bzoj1070][SCOI2007]修车_费用流
修车 bzoj-1070 SCOI-2007 题目大意:有m个人要修n台车,每个工人修不同的车的时间不同,问将所有的车都修完,最少需要花费的时间. 注释:$2\le m\le 9$,$1\le n \ ...
- ubuntu中安装hadoop集群
hadoop是由java 语言编写的主从结构分布式计算存储架构 准备工作: 操作系统: Ubuntu16.04 软件安装包:jdk-8u171-linux-x64.tar.gz : hadoop-2. ...
- 2015多校联合训练第一场Tricks Device(hdu5294)
题意:给一个无向图,给起点s,终点t,求最少拆掉几条边使得s到不了t,最多拆几条边使得s能到t 思路: 先跑一边最短路,记录最短路中最短的边数.总边数-最短边数就是第二个答案 第一个答案就是在最短路里 ...
- Android传统HTTP请求get----post方式提交数据(包括乱码问题)
1.模仿登入页面显示(使用传统方式是面向过程的) 使用Apache公司提供的HttpClient API是面向对象的 (文章底部含有源码的连接,包括了使用async框架) (解决中文乱码的问题.主要 ...