Linux 应用开发----socket编程笔记
Linux socket编程
套接字定义描述
套接字的域
- AF_INET ====>IPv4
- AF_INET6 ====>IPv6
- AF_UNIX ====>unix 域
- AF_UPSPEC ====>未使用
套接字的类型
- SOCK_DGRAM ====>固定长度,无链接的,不可靠的报文传递
- SOCK_RAM ====>IP协议数据报接口
- SOCK_SEQPACKET====>固定长度,有序,可靠的,面向连接的报文传递
- SOCK_STREAM ====>有序的,可靠的,双向的,面向连接的字节流
协议类型
- IPPROTO_IP ====>IPV4协议族
- IPPROTO_IPV6 ====>IPV6协议族
- IPPROTO_ICMP ====>控制报文协议
- IPPROTO_RAM ====>原始IP数据包
- IPPROTO_TCP ====>字节流传输控制协议
- IPPROTO_UDP ====>用户数据包协议
API
头文件
#include <sys/socket.h>
字节序
以太网中的字节序是大端的,因此相关的以太网的数据在小端机器上需要使用相关接口转换为以太网字节序。常用转换工具函数:
//4字节整形变量主机字节序的转换为网络字节序
uint32_t htonl(uint32_t hostint32);
//2字节整形变量主机字节序的转换为网络字节序
uint16_t htons(uint15_t hostint16);
//和上面相反
uint32_t ntohl(uint32_t netint32);
//和上面相反
uint32_t ntohl(uint32_t netint32);
常用接口(具体使用man 2 xxx 命令查看具体说明)
//创建套接字
int socket(int domain,int type,int protocol);
//将一个套接字和指定地址和端点关联起来
int bind(int sockfd,const struct sockaddr * addr,socklen_t addrlen);
//开始监听这个套接字
int listen(int socket, int backlog);
//向指定socket发起连接请求
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
//接收监听到的一个socket连接请求
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
//通过socket 发送数据,地址是socket默认
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
//通过socket 接收数据,地址为socket 默认
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
//通过socket 发送数据,地址是由参数指定
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
//通过socket 接收数据,地址由参数指定
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
//常用在unix 域下的进程通讯,发送数据
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
//常用在unix 域下的进程通讯,接收数据
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
//获取当前socket信息
int getsockname((int sockfd, const struct sockaddr *addr, socklen_t addrlen);
//获取原端socket信息(建立连接之后)
int getpeername((int sockfd, const struct sockaddr *addr, socklen_t addrlen);
关闭套接字
套接字关闭可以像关闭一个文件的描述符一样调用close()接口来关闭socket接口,除此之外还可以使用shutdown接口进行更加细致的关闭操作:
sockfd :sock描述符
how :SHUT_RDWR 读写两端都关闭
: SHUT_WR 关闭写端
: SHUT_RD 关闭读端
返回值 :成功返回0 失败返回-1
int shutdown(int sockfd,int how);
相关结构体
//描述网络信息
struct sockaddr_in {
s_add.sin_family = AF_INET;
s_add.sin_port = htons(1040);
s_add.sin_addr.s_addr = inet_addr("127.0.0.1");
};
TCP服务端配置过程
- 建立套接字,返回套接字
//建立 IPv4域下的字节流服务的TCP协议的socket
int sockfd_s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
- 将套接字和指定地址关联,使用上述的结构体描述端口和地址信息。
//将这个socket个特定地址何端口关联起来
bind(sockfd_s,(struct sockaddr*)&s_add,sizeof(struct sockaddr_in))
- 告诉系统套接字刻意监听链接。
//开始监听
listen(sockfd_s,1)
- 接受一个连接,这一步将返回新的套接字接口
//接受任意连接请求,返回可以用来数据传输的socket描述符
accept(sockfd_s,NULL,NULL);
TCP客户端配置过程
- 建立套接字,返回套接字
//建立 IPv4域下的字节流服务的TCP协议的socket
int sockfd_s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
- 连接到指定地址何端口
//向制定地址和端口发起链接请求
connect(sockfd_c,(struct sockaddr*)&c_add,sizeof(c_add))
示例代码
见文末
连接信息获取
获取本地套接字信息
获取远端套接字信息(连接后)
套接字选项
- 选项 类型(非特殊为int型) 描述
- SO_ACCEPTCONN 查询套接字是否可以被监听
- SO_BROADCAST 非0 广播数据报
- SO_DEBUG 非0 启用调试
- SO_ERROR 返回挂起套接字的错误并清除
- SO_KEEPALIVE 非0 启用keep-alive报文
- SO_OOBINLINE TCP 带外数据
- SO_RCVBUF 获取接收缓冲区的数据
- SO_RCVLOWAT 接受调用返回的最小字节数
- SO_RCVTIMEO struct timeval 接收调用的超时时间
- SO_REUSEADDR 重用地址,有用
- SO_SNDBUF 发送buf中的字节数
- SO_SNDLOWAT 发送传送的最小字节数
- SO_SNDTIMEO struct timeval 发送超时时间
- SO_TYPE 套接字类型标识,仅get可用
设置选项
int setsockopr(int sockfd,int level,int option,void *val,socklen_t len);
获取选项
int setsockopr(int sockfd,int level,int option,void *val);
带外数据
是一些通讯协议支持的可选功能,与普通数据相比其具有更高的优先级被传输。目前TCP的支持带外数据传输的,仅支持一个字节的紧急数据。有些实现TCP的带外数据还可以产生SIGURG信号。还可以通过下面的接口判断是否有紧急数据,当有紧急数据时,返回1。
iny sockatmark(int sockfd);
异步socket和非阻塞socket
基本上socket的异步IO和阻塞和非阻塞的处理和普通的文件基本相同,但是有一些区别的是,但是目前还没有完整的标准,视具体平台的实现情况。
示例demo
int main(int argc,int *argv)
{
char *name,i;
struct hostent* host;
size_t len = sysconf(_SC_HOST_NAME_MAX);
if(len>0){
name = malloc(len+1);
}else{
name = malloc(1024);
len = 1024;
}
printf("Buff size%ld\n",stdout->_IO_buf_end-stdout->_IO_buf_base);
if(gethostname(name,len)<0){
printf("gethostname error!\n");
}
host = gethostbyname(name);
if(*host->h_aliases){
printf("%s\n%s\n%s\n%d\n",
host->h_name,//host name
*host->h_aliases, //host_name aliases
(host->h_addrtype==AF_INET?"IP_V4":"IP_V6"),
host->h_length);
}else{
printf("%s\n%s\n%d\n",
host->h_name,
(host->h_addrtype==AF_INET?"IP_V4":"IP_V6"),
host->h_length);
}
for(i=0;host->h_addr_list[i] != NULL;i++){
printf("%s\n",inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
}
printf("befor the fork call\n\n");
int pid = fork();
if(pid){
int status,temp=1;
int sockfd_s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sockfd_s<0){
goto fail;
}
if(setsockopt(sockfd_s,SOL_SOCKET,SO_REUSEADDR,&temp,sizeof(int)) < 0)
{
perror("setsockopt");
}
struct sockaddr_in s_add;
s_add.sin_family = AF_INET;
s_add.sin_port = htons(1040);
s_add.sin_addr.s_addr = inet_addr("127.0.0.1");
// inet_pton(AF_INET,"127.0.0.1",&s_add.sin_addr);
if(bind(sockfd_s,(struct sockaddr*)&s_add,sizeof(s_add))<0){
printf("1\n");
goto fail;
}
if(listen(sockfd_s,1)<0){
goto fail;
}
int c_fd = accept(sockfd_s,NULL,NULL);
if(c_fd < 0){
goto fail;
}
int len=sizeof(s_add);
if(getpeername(c_fd,(struct sockaddr*)&s_add,&len)<0){
printf("2\n");
goto fail;
}
printf("server:\n%s\n%d\n",inet_ntoa(s_add.sin_addr),ntohs(s_add.sin_port));
if(c_fd){
while(1){
char buf[64];
recv(c_fd,buf,64,0);
printf("%s\n",buf);
sleep(1);
}
}
fail:
close(sockfd_s);
perror(strerror(errno));
kill(pid,9);
waitpid(pid,&status,0);
printf("server end\n");
return 0;
}else if(!pid){
sleep(3);
int sockfd_c = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sockfd_c<0){
goto fail_c;
}
struct sockaddr_in c_add;
c_add.sin_family = AF_INET;
c_add.sin_port = htons(1040);
c_add.sin_addr.s_addr = inet_addr("127.0.0.1");
// inet_pton(AF_INET,"127.0.0.1",&c_add.sin_addr);
if(connect(sockfd_c,(struct sockaddr*)&c_add,sizeof(c_add))){
goto fail_c;
}
struct sockaddr_in d_add;
int len=sizeof(d_add);
if(getpeername(sockfd_c,(struct sockaddr*)&d_add,&len)<0){
goto fail_c;
}
printf("cliens\n%s\n%d\n",inet_ntoa(d_add.sin_addr),ntohs(d_add.sin_port));
while(1)
{
send(sockfd_c,"hello word!\n",strlen("hello word!\n"),0);
sleep(1);
}
fail_c:
close(sockfd_c);
perror(strerror(errno));
_exit(0);
}
return 0;
}
Linux 应用开发----socket编程笔记的更多相关文章
- C# Socket编程笔记(转)
C# Socket编程笔记 http://www.cnblogs.com/stg609/archive/2008/11/15/1333889.html TCP Socket:Server 端连接步骤: ...
- Linux学习之socket编程(二)
Linux学习之socket编程(二) 1.C/S模型——UDP UDP处理模型 由于UDP不需要维护连接,程序逻辑简单了很多,但是UDP协议是不可靠的,实际上有很多保证通讯可靠性的机制需要在应用层实 ...
- Linux学习之socket编程(一)
socket编程 socket的概念: 在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程,“IP地址+端口号”就称为socket. 在TCP协议中,建立连接的两个进 ...
- iOS开发— Socket编程
Socket编程 一.了解网络各个协议:TCP/IP.SOCKET.HTTP等 网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 其中物理层.数据链路层和网络层通常被 ...
- python3全栈开发-socket编程
一. 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务端为你提供视 ...
- python socket编程笔记
用python实现一个简单的socket网络聊天通讯 (Linux --py2.7平台与windows--py3.6平台) 人生苦短之我用Python篇(socket编程) python之路 sock ...
- Linux下Golang Socket编程原理分析与代码实现
在POSIX标准推出后,socket在各大主流OS平台上都得到了很好的支持.而Golang是自带Runtime的跨平台编程语言,Go中提供给开发者的Socket API是建立在操作系统原生Socket ...
- Java套接字socket编程笔记
相对于C和C++来说,Java中的socket编程是比较简单的,比较多的细节都已经被封装好了,每次创建socket连接只需要知道地址和端口即可. 在了解socket编程之前,我们先来了解一下读写数据的 ...
- 网络编程学习笔记:linux下的socket编程
socket是进程通信的一种方式,通过调用一些API可以实现进程间通信,建立连接以及收发信息的过程如下图所示: 这些函数的用法如下: 1.int socket(int protocolFamily, ...
随机推荐
- 面对key数量多和区间查询低效问题:Hash索引趴窝,LSM树申请出场
摘要:Hash索引有两个明显的限制:(1)当key的数量很多时,维护Hash索引会给内存带来很大的压力:(2)区间查询很低效.如何对这两个限制进行优化呢?这就轮到本文介绍的主角,LSM树,出场了. 我 ...
- Code Review 的几个技巧
No magic: Explicit not implicit: 覆盖度比深度重要,覆盖度追求100%: 频率比仪式感重要,坐公交蹲厕所打开手机都可以 Review 别人代码,不需要专门组织会议: 粒 ...
- 什么是 MVC 模式
概述 MVC,即 Model 模型.View 视图,及 Controller 控制器. View:视图,为用高糊提供使用界面,与用户直接进行交互. Model:模型,承载数据,并对用户提交请求进行计算 ...
- __new__() to create it, and __init__() to customize it 类方法 实例方法
https://docs.python.org/3/reference/datamodel.html#object.__init__
- 阿里云 Redis 开发规范
阿里云Redis开发规范-阿里云开发者社区 https://developer.aliyun.com/article/531067 https://mp.weixin.qq.com/s/UWE1Kx6 ...
- 最简单直接地理解Java软件设计原则之单一职责原则
理论性知识 定义 单一职责原则, Single responsibility principle (SRP): 一个类,接口,方法只负责一项职责: 不要存在多余一个导致类变更的原因: 优点 降低类的复 ...
- nodejs如何下载指定版本
浏览了一下nodejs的官网,但是官网没有下载低版本的下载地址,所以找了一个可以下载指定版本node的下载地址https://nodejs.org/download/release/v8.9.4/
- 《我想进大厂》之Zookeeper夺命连环9问
谈谈你对Zookeeper的理解? Zookeeper是一个开源的分布式协调服务,由雅虎公司创建,由于最初雅虎公司的内部研究小组的项目大多以动物的名字命名,所以后来就以Zookeeper(动物管理员) ...
- SpringBoot整合JavaMail发送邮件
JavaMail是SUN提供给广大Java开发人员的一款邮件发送和接受的一款开源类库,支持常用的邮件协议,如:SMTP.POP3.IMAP,开发人员使用JavaMail编写邮件程序时,不再需要考虑底层 ...
- multiselect多选下拉框
具体实现 <input type="hidden" id="q_dueDay" name="q_dueDay" value=" ...