linux网络socket 接口转
linux网络socket 接口
1、socket函数:一个进程必须做的第一件事就是调用socket函数获得一个文件描述符。
|
第一个参数指明了协议簇,目前支持5种协议簇,最常用的有AF_INET(IPv4协议)和AF_INET6(IPv6协议);第二个参数指明套接口类型,有三种类型可选:SOCK_STREAM(字节流套接口)、SOCK_DGRAM(数据报套接口)和SOCK_RAW(原始套接口);如果套接口类型不是原始套接口,那么第三个参数就为0.
|
2、connect函数:当用socket建立了套接口后,可以调用connect为这个套接字指明远程端的地址;如果是字节流套接口,connect就使用三次握手建立一个连接;如果是数据报套接口,connect仅指明远程端地址,而不向它发送任何数据。
|
第一个参数是socket函数返回的套接口描述字;第二和第三个参数分别是一个指向套接口地址结构的指针和该结构的大小。这些地址结构的名字均已“sockaddr_”开头,并以对应每个协议族的唯一后缀结束。以IPv4套接口地址结构为例,它以“sockaddr_in”命名,定义在头文件;以下是结构体的内容:
|
|
3、bind函数:为套接口分配一个本地IP 和协议端口,对于网际协议,协议地址是32位IPv4地址或128位IPv6地址与16位的TCP或UDP端口号的组合;如指定端口为0,调用bind时内核将选择一个临时端口,如果指定一个通配IP地址,则要等到建立连接后内核才选择一个本地IP地址。
|
第一个参数是socket函数返回的套接口描述字;第二和第第三个参数分别是一个指向特定于协议的地址结构的指针和该地址结构的长度。
|
4、listen函数:listen函数仅被TCP服务器调用,它的作用是将用sock创建的主动套接口转换成被动套接口,并等待来自客户端的连接请求。
|
第一个参数是socket函数返回的套接口描述字;第二个参数规定了内核为此套接口排队的最大连接个数。由于listen函数第二个参数的原因,内核要维护两个队列:以完成连接队列和未完成连接队列。未完成队列中存放的是TCP连接的三路握手为完成的连接,accept函数是从以连接队列中取连接返回给进程;当以连接队列为空时,进程将进入睡眠状态。
|
5、accept函数:accept函数由TCP服务器调用,从已完成连接队列头返回一个已完成连接,如果完成连接队列为空,则进程进入睡眠状态。
|
第一个参数是socket函数返回的套接口描述字;第二个和第三个参数分别是一个指向连接方的套接口地址结构和该地址结构的长度;该函数返回的是一个全新的套接口描述字;如果对客户段的信息不感兴趣,可以将第二和第三个参数置为空。
|
6、inet_pton函数:将点分十进制串转换成网络字节序二进制值,此函数对IPv4地址和IPv6地址都能处理。
|
第一个参数可以是AF_INET或AF_INET6:第二个参数是一个指向点分十进制串的指针:第三个参数是一个指向转换后的网络字节序的二进制值的指针。
7、inet_ntop函数:和inet_pton函数正好相反,inet_ntop函数是将网络字节序二进制值转换成点分十进制串。
|
第一个参数可以是AF_INET或AF_INET6:第二个参数是一个指向网络字节序的二进制值的指针;第三个参数是一个指向转换后的点分十进制串的指针;第四个参数是目标的大小,以免函数溢出其调用者的缓冲区。
8、fork函数:在网络服务器中,一个服务端口可以允许一定数量的客户端同时连接,这时单进程是不可能实现的,而fork就分配一个子进程和客户端会话,当然,这只是fork的一个典型应用。
|
fork函数调用后返回两次,父进程返回子进程ID,子进程返回0。
TCP 系统调用序列
http://www.ibm.com/developerworks/cn/aix/library/au-tcpsystemcalls/
典型的 TCP 客户机和服务器应用程序通过发布 TCP 系统调用序列来获取某些函数。这些系统调用包括 socket ()
、bind ()
、listen ()
、accept ()
、send ()
和 receive()
。本文介绍在应用程序发布 TCP 系统调用时在较低级别中发生的情况,如图 1 所示。
图 1. TCP 应用程序进行的普通调用序列
[]
TCP套接字使用TCP建立连接,建立一个TCP连接需要三次握手,基本过程是服务器先建立一个套接口并等待客户端的连接请求;当客户端调用 connect进行主动连接请求时,客户端TCP发送一个SYN,告诉服务器客户端将在连接中发送的数据的初始序列号;当服务器收到这个SYN后也给客户端发一个SYN,里面包含了服务器将在同一连接中发送的数据的初始序列号;最后客户在确认服务器发的SYN。到此为止,一个TCP连接被建立。
下面就用一个例子来说明服务器和客户是怎么连接的
|
现在让我们来编译这两个程序:
|
然后在一台计算机上先运行服务器程序,再在另一个终端上运行客户端就会看到结果;如果不运行服务器程序而先运行客户程序将立即提示"Connect: Connection refused",这就是TCP套接口的好处,如果是UDP套接口将会有一个延时才会得到错误信息(UDP套接口后面有介绍)。
建立一个TCP连接需要三次握手,而断开一个TCP则需要四个分节。当某个应用进程调用close(主动端)后(可以是服务器端,也可以是客户端),这一端的TCP发送一个FIN,表示数据发送完毕;另一端(被动端)发送一个确认,当被动端待处理的应用进程都处理完毕后,发送一个FIN到主动端,并关闭套接口,主动端接收到这个FIN后再发送一个确认,到此为止这个TCP连接被断开。
UDP套接口
UDP套接口是无连接的、不可靠的数据报协议;既然他不可靠为什么还要用呢?其一:当应用程序使用广播或多播是只能使用UDP协议;其二:由于他是无连接的,所以速度快。因为UDP套接口是无连接的,如果一方的数据报丢失,那另一方将无限等待,解决办法是设置一个超时。
在编写UDP套接口程序时,有几点要fork注意:建立套接口时socket函数的第二个参数应该是SOCK_DGRAM,说明是建立一个UDP套接口;由于UDP是无连接的,所以服务器端并不需要listen或accept函数;当UDP套接口调用connect函数时,内核只记录连接放的IP地址和端口,并立即返回给调用进程,正因为这个特性,UDP服务器程序中并不使用fork函数,用单进程就能完成所有客户的请求。
UDP的协议头由4个字段组成:目标端口、源端口、长度和校验和。其中目标端口和源端口惟一确定了发送和接收数据的本地和远程进程;长度字段指出了数据报的字节数;校验和字段是可选的,可以置为0,也可以包含一个合法的校验和。
创建UDP客户端的典型过程为:首先调用socket( )函数,接下来定义发送和接收数据的远程主机和端口,然后将套接字传递给connect( )函数。套接字描述符在后面会用于发送和接收数据。除此之外,发送数据的目标主机和端口可以在数据“写入”时指定,这样就可以用一个套接字发送数据到多个主机。
UDP数据报的发送可以使用write( )、send( )或sendto( )函数。如果使用write( )或send( ),则必须事先以UDP套接字为参数调用connect( )函数,此外,如果使用sendto( )函数则可以在发送数据时再指定目标地址及端口。
接收UDP数据报可以使用read( )、recv( )或recvfrom( )函数。如果使用read( )或recv( ),则必须事先调用connect( )函数;如果使用recvfrom( ),则可以在接收数据报时获得源IP地址和端口。
接收到的UDP数据报的读取是一个单独的操作,如果读取报文时提供的缓冲区长度不够,则会返回一个出错代码。如果UDP数据报的长度超出了本地或者任意一个必经的网络上的最大片长度,则必须进行分段,这在性能上会有不良影响,因此有些操作系统对此做了限制或者不予支持。
/*
* udp2.c
*
* send UDP datagram using socket descriptor that has been passed
* to connect().
*/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define UDP2_DST_ADDR "127.0.0.1"
#define UDP2_DST_PORT 1234
int main(void)
{
struct sockaddr_in sin;
char buf[100];
int sock = 0;
int ret = 0;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0)
{
printf("socket() failed./n");
return(1);
}
memset(&sin, 0x0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(UDP2_DST_PORT);
sin.sin_addr.s_addr = inet_addr(UDP2_DST_ADDR);
ret = connect(sock, (struct sockaddr *) &sin, sizeof(sin));
if(ret < 0)
{
printf("connect() failed./n");
return(1);
}
memset(buf, 'A', 100);
ret = send(sock, buf, 100, 0);
if(ret != 100)
{
printf("send() failed./n");
return(1);
}
close (sock);
printf("send() success./n");
return(0);
}
------------------------------------------------------------------------
/*
* udp3.c
*
* send UDP datagram using socket descriptor and sendto().
*
* foster <jamescfoster@gmail.com>
*/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define UDP3_DST_ADDR "127.0.0.1"
#define UDP3_DST_PORT 1234
int main(void)
{
struct sockaddr_in sin;
char buf[100];
int sock = 0;
int ret = 0;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0)
{
printf("socket() failed./n");
return(1);
}
memset(&sin, 0x0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(UDP3_DST_PORT);
sin.sin_addr.s_addr = inet_addr(UDP3_DST_ADDR);
memset(buf, 'A', 100);
ret = sendto(sock, buf, 100, 0,(struct sockaddr *) &sin, sizeof(sin));
if(ret != 100)
{
printf("sendto() failed./n");
return(1);
}
close(sock);
printf("sendto() success./n");
return(0);
}
------------------------------------------------------------------
setsockopt()函数允许在网络协议的不同层次对参数进行调整,套接字选项最常用于在套接字层调整参数,包括调整错误处理、数据缓冲、地址处理、端口处理和收发数据的超时参数等。
在默认情况下,read()、recv()和recvfrom()函数以阻塞方式读取数据,当函数被调用时,将会无限期地等待,直到数据被接收或出现错误。如果在某种实现情况下必须在数据未能及时到达时做出反应,则这种行为是不符合要求的。
int makeudpsock (char *dst, unsigned short port)
{
struct sockaddr_in sin;
struct timeval tv; //超时处理
unsigned int taddr = 0;
int sock = 0;
int ret = 0;
taddr = inet_addr(targ);
if(taddr == INADDR_NONE)
{
printf("inet_addr() failed./n");
return(-1);
}
sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0)
{
printf("socket() failed./n");
return(-1);
}
memset(&sin, 0x0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = taddr;
ret = connect(sock, (struct sockaddr *) &sin, sizeof(sin));
if(ret < 0)
{
printf("connect() failed./n");
return(-1);
}
memset(&tv, 0x00, sizeof(tv));
tv.tv_sec = 10;
ret = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
if(ret < 0)
{
printf("setsockopt() failed./n");
return(-1);
}
return(sock);
在此例中,使用socket()和connect()函数创建了一个UDP套接字,并将它与一个远程端点关联,然后使用setsockopt()函数设置了这个套接字的接收超时参数,超时参数存放在一个timeval结构中。最后,函数将创建的套接字作为返回值返回。
linux网络socket 接口转的更多相关文章
- linux 网络Socket实战
Preface:就算调通API,也不值得太过自豪!!!悉心细心学习,最好的深度学习就是看-学...*.h/*.class ProtoType; 1,linux C ftp C/S简单实现 ftpS端码 ...
- 理解 Linux 网络栈(3):QEMU/KVM + VxLAN 环境下的 Segmentation Offloading 技术(发送端)
本系列文章总结 Linux 网络栈,包括: (1)Linux 网络协议栈总结 (2)非虚拟化Linux环境中的网络分段卸载技术 GSO/TSO/UFO/LRO/GRO (3)QEMU/KVM + Vx ...
- 深入理解linux网络技术内幕读书笔记(三)--用户空间与内核的接口
Table of Contents 1 概论 1.1 procfs (/proc 文件系统) 1.1.1 编程接口 1.2 sysctl (/proc/sys目录) 1.2.1 编程接口 1.3 sy ...
- Linux 网络子系统之网络协议接口层(一)
Linux 网络设备驱动之网络协议接口层介绍. 网络协议接口层最主要的功能是给上层协议提供透明的数据包发送和接收接口. 当上层ARP或IP需要发送数据包时,它将调用网络协议接口层的dev_queue_ ...
- Linux网络编程:UDP Socket编程范例
TCP协议提供的是一种可靠的,复杂的,面向连接的数据流(SOCK_STREAM)传输服务,它通过三段式握手过程建立连接.TCP有一种"重传确认"机制,即接收端收到数据后要发出一个肯 ...
- linux网络编程之socket编程(四)
经过两周的等待,终于可以回归我正常的学习之旅了,表哥来北京了在我这暂住,晚上回家了基本在和他聊天,周末带他在北京城到处乱转,几乎剥夺了我自由学习的时间了,不过,亲人之情还是很难得的,工作学习并不是生活 ...
- linux网络编程之socket编程(六)
经过一个国庆长假,又有一段时间没有写博文了,今天继续对linux网络编程进行学习,如今的北京又全面进入雾霾天气了,让我突然想到了一句名句:“真爱生活,珍惜生命”,好了,言归正传. 回顾一下我们之间实现 ...
- linux网络环境下socket套接字编程(UDP文件传输)
今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...
- linux网络编程-(socket套接字编程UDP传输)
今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...
随机推荐
- 小白菜OJ 1122 公牛母牛配(最大二分图匹配模板)
题意: n只公牛和m只母牛,某些公牛和某些母牛互相喜欢.但最后一只公牛只能和一只母牛建立一对一匹配.要使得最后牛群匹配对数最大. 链接: http://caioj.cn/problem.php?id= ...
- sql中Distinct&Count的用法
Distinct作用:消除重复的数值 1.如: select id from T1 select distinct id from T1 二者的检索效果如下: distinct可以用来修饰多列,如: ...
- sed之h;H和:a;N;ba使用精解(对段落进行操作)
1) 文本: Handle 0x0058, DMI type 20, 19 bytes Memory Device Mapped Address Starting Address: 0 ...
- c#如何判断textbox中输入的数据是datatime型的
()你好,标准的方法是用一个验证控件:RangeValidator,把type设为DateTime,最大值设为'3000-1-1'或者别的,最小值最好设为'1900-1-1'. ()程序里面自己验证: ...
- loadrunner报错-持续更新
一.关联使用web_reg_save_param报错 1.以下是网页中需要关联的地方,有2处,通过网页查看源代码可以看: 2.还可以通过Generation Log来查看需要关联的地方: 3. 然后再 ...
- Python中input()和raw_input()函数的区别
问题:在Python2.7中使用 input() 函数会出现 “NameError: Name ”***“ is not defined 的错误 解决: 使用raw_input() 函数,在Pytho ...
- MVC4 上传图片并生成缩略图
Views @using (Html.BeginForm("Create","img",FormMethod.Post, new { enctype = &qu ...
- 七牛云 X 英语流利说:教育 3.0 时代的智能突破
美国当地时间 2018 年 9 月 27 日,国内领先的人工智能驱动的教育科技公司「英语流利说」正式挂牌纽交所,以其独创的教育 3.0 模式,成为中国「AI+ 教育」第一股. 教育 3.0 时代的智能 ...
- 操作redis有关的命令
)连接操作命令 quit:关闭连接(connection) auth:简单密码认证 help cmd: 查看cmd帮助,例如:help quit )持久化 save:将数据同步保存到磁盘 bgsave ...
- 搭建Spring+mybatis报错
java.lang.ClassCastException: com.sun.proxy.$Proxy12 cannot be cast to com.bdqn.service.impl.UserSer ...