Linux IPC tcp/ip socket 编程
模型

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//服务器:
socket() //创建socket
struct sockaddr_in //准备通信地址
bind() //绑定socket和addr
listen() //创建listening socket
accept() //创建connect socket
send()/recv() //进行通信
close() //关闭socket
//客户端:
socket() //创建socket
准备通信地址:服务器的地址
connect() //链接socket和通信地址
send()/recv() //进行通信
close() //关闭socket
socket()
//创建网络端点,返回socket文件描述符,失败返回-1设errno
int socket(int domain, int type, int protocol);
domain :协议族(protocol family)(网络通讯(IP)还是本地通讯(xxx.socket))
- AF_INET用于实现给予ipv4网络协议的网络协议
type :协议(TCP还是UDP)
- SOCK_STREAM //流式套接字, 实现包括但不限于TCP协议,which is有序,可靠双向面向连接的字节流通信方式
protocol: 特殊协议, 一般给0
准备通信地址:
struct sockaddr{ //主要用于函数的形参类型, 很少定义结构体变量使用, 叫做通用的通信地址类型//$man bind
sa_family_t sa_family;
char sa_data[14];
}
struct sockaddr_in{ //准备网络通信的通信地址 //$man in.h
sa_family_t sin_family; //协议族, 就是socket()的domain的AF_INET
in_port_t sin_port; //端口号
struct in_addr sin_addr; //IP地址
}
struct in_addr{
in_addr_t s_addr; //整数类型的IP地址
}
bind():
//把通信地址和socket文件描述符绑定,用在服务器端,成功返回0,失败返回-1设errno
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd: socket文件的fd(returned by socket())
addr: 需要强制类型转换成socketaddr_un或soketaddr_in, 参见上
addrlen: 通信地址的大小, 使用sizeof();
listen()
//创建侦听socket,把sockfd标记的socket标记为被动socket,被动socket表示这个socket只能用来接收即将到来的连接请求,不再用于读写操作和通信,接收连接请求的是accept()
//成功返回0,失败返回-1设errno
int listen(int sockfd, int backlog);
backlog:排队等待“被响应”连接请求队列的最大长度 eg: 接待室的最大长度
accept()
//创建连接socket,返回连接socket的文件描述符,成功返回文件描述符,失败返回-1设errno
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
addr : 结构体指针, 用于带出客户端的通信地址
addlen : 结构体指针, 用于带出通信地址的大小
ATTENTION: listen()把socket()创建的sockfd变为listening socket, 负责侦听哪个client连接上了(即不但要知道连上没, 还要知道谁连上了, 这个SOCK_STREAM的socket有这个能力), accept()提取排队中的最上面的一个client, 给它一个conneted socket, 这样这个client就可以和server沟通了, 就是说这里有两个socket, 一个负责侦听一个负责通信
send()
//向指定的socket发送指定的数据,成功返回实际发送数据的大小,失败返回-1设errno
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
sockfd: 用于通信的socket描述符(returned by accept())
buf : 被发送数据的缓冲区首地址
len : 被发送数据的大小
flags: 发送的标志, 如果给0等同于write()
recv()
//从指定的socket接收数据,成功返回接收的数据的大小,失败返回-1设errno
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
sockfd: 用于通信的socket描述符(returned by accept())
buf: 接收数据的缓冲区首地址
len: 接收数据的大小
flags: 发送的标志, 如果给0等同于read()
connect():
//初始化一个socket的连接,用在客户端,成功返回0,失败返回-1设errno
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd: socket文件的fd(returned by socket())
addr: 需要强制类型转换成socketaddr_un或soketaddr_in, 参见上
addrlen: 通信地址的大小, 使用sizeof();
例子-多进程并发tcp/ip协议服务器模型
除了这种多进程的并发模型,还有多线程并发和I/O多路复用并发等方式
//创建server, 用多进程同时响应多个client的请求, 当client发来 “bye”的时候断开连接, 按下Ctrl+C关闭服务器
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h> //省略了几个头文件
int sockfd; //全局变量
void fa(int signo){
printf("closing server...\n");
sleep(3);
int res=close(sockfd);
if(-1==res)
perror("close"),exit(-1);
printf("server closed\n");
exit(0);
}
int main(){
//1.创建socket socket()
int sockfd=socket(AF_INET,SOCK_STREAM,0);
if(-1==sockfd)
perror("socket"),exit(-1);
printf("creat socket success\n");
//2.准备通信地址(服务器地址),使用结构体类型
struct sockaddr_in addr={0}; //要初始化为0
addr.sin_family=AF_INET;
addr.sin_port=htons(8888);
addr.sin_addr.s_addr=inet_addr("176.43.11.211"); //client也用这个server的地址
//3.绑定socket和通信地址,使用bind()
int res=bind(sockfd, (struct sockaddr*)&addr,sizeof(addr)); //client用connect
if(-1==res)
perror("bind"),exit(-1);
printf("bind success\n");
//4.生成侦听socket: listening socket listen() //client可没有这一步
res=listen(sockfd,100);
if(-1==res)
perror("listen"),exit(-1);
printf("listen success\n");
//set SIGINT
printf("Press ctrl+c to close server\n");
if(SIG_ERR==signal(SIGINT,fa)) //整个程序,包括第一个while(1)是通过信号处理终止的
perror("signal"),exit(-1);
while(1){ //只要有client接入就创建新进程与之通信
struct sockaddr_in recv_addr;
socklen_t len=sizeof(recv_addr);
int CnnSockfd=accept(sockfd,(struct sockaddr*)&recv_addr,&len);
//如果侦听队列里面有client就accept(), 否则就在这阻塞着,不继续执行,除非遇到Ctrl+C终止整个进程
if(-1==CnnSockfd)
perror("accept"),exit(-1);
char *ip=inet_ntoa(recv_addr.sin_addr);
printf("client:%s linked\n",ip);
pid_t pid=fork();
if(-1==pid)
perror("fork()"),exit(-1);
if(0==pid){
if(SIG_ERR==signal(SIGINT,SIG_DFL))
perror("signal"),exit(-1);
//每个child处理一个client,所以已经不需要listening socket了,可以把它关了
//如果不关子进程也会有一个listenfd,会和父进程一起抢,不应该
res=close(sockfd);
if(-1==res)
perror("close"),exit(-1);
while(1){ //只要client发数据就处理,除非遇到 “bye”
char buf[100]={0};
res=recv(CnnSockfd,buf,sizeof(buf),0);
if(-1==res)
perror("recv"),exit(-1);
printf("client%s,data sent:%s\n",ip,buf);
if(!strcmp(buf,"bye")){ //遇到“bye”就不再待命,break掉准备断开连接
printf("client%s has been unlinked\n",ip);
break;
}
res=send(CnnSockfd,"I received!",12,0);
if(-1==res)
perror("send"),exit(-1);
}
res=close(CnnSockfd); //断开连接即close(相应的connected socket)
if(-1== res)
perror("close"),exit(-1);
exit(0); //断开了连接了,就可以exit子进程了
}
res=close(CnnSockfd); //
if(-1==res)
perror("close"),exit(-1);
}
return 0;
}
Linux IPC tcp/ip socket 编程的更多相关文章
- Linux IPC udp/ip socket 编程
模型 #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include < ...
- 一个项目看java TCP/IP Socket编程
前一段时间刚做了个java程序和网络上多台机器的c程序通讯的项目,遵循的是TCP/IP协议,用到了java的Socket编程.网络通讯是java的强项,用TCP/IP协议可以方便的和网络上的其他程序互 ...
- 《Java TCP/IP Socket 编程 》读书笔记之十一:深入剖析socket——TCP套接字的生命周期
转载请注明出处:http://blog.csdn.net/ns_code/article/details/16113083 建立TCP连接 新的Socket实例创建后,就立即能用于发送和接收 ...
- 浅谈TCP/IP网络编程中socket的行为
我认为,想要熟练掌握Linux下的TCP/IP网络编程,至少有三个层面的知识需要熟悉: 1. TCP/IP协议(如连接的建立和终止.重传和确认.滑动窗口和拥塞控制等等) 2. Socket I/O系统 ...
- Linux下的C Socket编程 -- 获取对方IP地址
Linux下的C Socket编程(二) 获取域名对应的IP地址 经过上面的讨论,如果我们想要连接到远程的服务器,我们需要知道对方的IP地址,系统函数gethostbyname便能够实现这个目的.它能 ...
- Linux内核 TCP/IP、Socket参数调优
Linux内核 TCP/IP.Socket参数调优 2014-06-06 Harrison.... 阅 9611 转 165 转藏到我的图书馆 微信分享: Doc1: /proc/sy ...
- Linux下的C Socket编程 -- 简介与client端的处理
Linux下的C Socket编程(一) 介绍 Socket是进程间通信的方式之一,是进程间的通信.这里说的进程并不一定是在同一台机器上也有可能是通过网络连接的不同机器上.只要他们之间建立起了sock ...
- ZT Linux系统环境下的Socket编程详细解析
Linux系统环境下的Socket编程详细解析 来自: http://blog.163.com/jiangh_1982/blog/static/121950520082881457775/ 什么是So ...
- TCP/IP网络编程系列之三(初级)
TCP/IP网络编程系列之三-地址族与数据序列 分配给套接字的IP地址和端口 IP是Internet Protocol (网络协议)的简写,是为首发网络数据而分配给计算机的值.端口号并非赋予计算机值, ...
随机推荐
- python学习笔记12 ----线程、进程
进程和线程的概念 进程和线程是操作系统中两个很重要的概念,对于一般的程序,可能有若干个进程,每一个进程有若干个同时执行的线程.进程是资源管理的最小单位,线程是程序执行的最小单位(线程可共享同一进程里的 ...
- linux下搭建php的集成环境
一个偶然的机会,在项目中需要搭建PHP的环境,由于PHP开发需要的东西比较多,像apache.mysql.PHP环境等,如果一个一个装很可能会有安装不全的问题,为此选择了安装集成环境,这里选择的是xa ...
- 我们为什么要配置CATALINA_HOME环境变量
用文本编辑工具打开用于启动Tomcat的批处理文件startup.bat,仔细阅读.在这个文件中,首先判断CATALINA_HOME环境变量是否为空,如果为空,就将当前目录设为CATALINA_HOM ...
- 在 Windows 上遇到非常多 TIME_WAIT 連線時應如何處理
我們公司所代管的網站裡,有幾個流量是非常大的,在尖峰的時刻同時上線人數可能高達數千到數萬人,而在這個時候如果使用 netstat 或 TCPView 查看所有 TCP 連線時就會看到非常多處於 ...
- Entity Framework 笔记(一)
Entity Framework概述 EF是一个对象关系映射(ORM)框架,允许开发人员使用特定于域的对象关系型数据,开发人员通常不需要编写大量的数据访问代码.使用EF,开发者可以利用LINQ进行查询 ...
- this指向问题
我今天下午本来想做个就是tr鼠标移出之后过三秒把对应的input添加hiddens类 然后我就这样写了 $('.table>tbody>tr').mouseout(function(){ ...
- CSS3与页面布局学习笔记(三)——BFC、定位、浮动、7种垂直居中方法
一.BFC与IFC 1.1.BFC与IFC概要 BFC(Block Formatting Context)即“块级格式化上下文”, IFC(Inline Formatting Context)即行内格 ...
- Kickoff - 创造可扩展的,响应式的网站
Kickoff 是一个轻量级的前端框架,用于创建可扩展的,响应式的网站.作为前端开发人员,我们工作的类型越来越多样化.Kickoff 旨在帮助您在所有项目保持一致的结构和风格,无需添加其他框架. 在线 ...
- atom编辑markdown之上传图片
01atom编辑markdown之上传图片 :first-child { margin-top: 0px; } .markdown-preview:not([data-use-github-style ...
- overflow 属性
写在前面的话: 2016年5月4日青年节,作为一名正青春的学生党,开始了博客生涯,励志做个勤奋上进的好青年.幻想着毕业后月薪W+ .走上人生巅峰的职场生活...... 然而 然而 然而 ,自制力有限的 ...