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, ...
随机推荐
- 微服务网关1-Spring Cloud Gateway简介
一.网关基本概念 1.API网关介绍 API 网关出现的原因是微服务架构的出现,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各 ...
- watchdog应用实例
watchdog应用实例 By 鬼猫猫 20130504 http://www.cnblogs.com/muyr/ 实例:监测某文件夹,一旦文件夹里有文件,就把它剪切到其他服务器 import sys ...
- gstack pstack strace
gstack pstack strace 通过进程号 查看 进程的工作目录 Linux神器strace的使用方法及实践 - 知乎 https://zhuanlan.zhihu.com/p/180053 ...
- WireShark 之 text2pcap
前言 本来想用 010Editer 的,看到破解教程头都大了,那么就用 WireShark 的 Text2pcap 吧! 正文 打开CMD控制台窗口,转到WireShark安装目录 ,此处可以shif ...
- cookie,session,token傻傻分不清
什么是认证(Authentication) • 通俗地讲就是验证当前用户的身份,证明"你是你自己"(比如:你每天上下班打卡,都需要通过指纹打卡,当你的指纹和系统里录入的指纹相匹配时 ...
- Android LocationManagerService启动(一)
Location服务是系统中很重要的一个服务,几乎当前所有的App都会用到这个服务. 首先看代码在Android源码的位置 Android API frameworks/base/location L ...
- 静电、浪涌与TVS
ESD和浪涌问题往往是基带工程师最头疼的问题,因为测试标准严苛,问题神出鬼没.特别是ESD问题,没有解决问题的标准路径,只能靠反复地构思方案并验证.想要尽量避免以上问题,就必须选择合适的防护器件,设计 ...
- UI自动化测试实战
前言 前面我们已经搭建好了wordpress网站,如果需要查看运行效果可以看我前面的搭建文章,下面我们来进行自动化测试的练习. 示例 首先我们测试自动登陆 import unittest from s ...
- loj10004智力大冲浪
题目描述 小伟报名参加中央电视台的智力大冲浪节目.本次挑战赛吸引了众多参赛者,主持人为了表彰大家的勇气,先奖励每个参赛者 m 元.先不要太高兴!因为这些钱还不一定都是你的?!接下来主持人宣布了比赛规则 ...
- 用hyper-v创建虚拟机
1.新建虚拟机 1) 2) 3) 4)一般情况:linux选择第一代,Windows选择第二代 5) 6) 7) 8) 9) 10) 11)网卡设置:如果虚拟机和宿主机公用一块网卡,那么VLAN ID ...