Linux网络编程基础及多线程并发案例
目录
1.ip:端口 TCP/IP协议
2.socket 头文件 sys/socket.h
3.字节序
4.ip地址转换函数
5.sockaddr和sockaddr_in
6.服务器端基本函数 bind listen accept
7.客户端基本函数 connect
8.send 和 recv
8.多线程
9.通信流程
10.多线程并发样例程序
1.ip:端口 TCP/IP协议
AF_INET IPv4
AF_INET6 IPv6SOCK_STREAM tcp协议
2.socket 头文件 sys/socket.h
套接字对应程序猿来说就是一套网络通信的接口,使用这套接口就可以完成网络通信。
网络通信的主体主要分为两部分:客户端和服务器端
int socket(int domain, int type, int protocol);
(1)在参数表中,domain指定使用何种的地址类型,比较常用的有:
PF_INET, AF_INET: Ipv4网络协议;
PF_INET6, AF_INET6: Ipv6网络协议。
(2)type参数的作用是设置通信的协议类型,可能的取值如下所示:
SOCK_STREAM: 提供面向连接的稳定数据传输,即TCP协议。
(3)一般取0即可
3.字节序
ittle-Endian -> 主机字节序 (小端)
Big-Endian -> 网络字节序 (大端)
头文件:#include <arpa/inet.h> //包含 sys/socket.h
uint16_htons(uint16_t hostshort) //短整形 主机字节序 --> 网络字节序
uint32_htonl(uint32_t hostlong) //长整形 主机字节序 -->网络字节序uint16_ntohs(uint16_t netshort) //短整形 网络字节序 -->主机字节序
uint32_ntohl(uint32_t netlong) //长整形 网络字节序 -->主机字节序
4.ip地址转换函数
int inet_pton(int af,const char *src,void *dst) //主机ip地址 -->网络ip字节序
注: 主机ip地址是字符串 、网络ip字节序是整形
(1) af : IP协议 AF_INET、AF_INET6
(2) src: 传入参数 十进制的ip地址
(3) dst:大整形ip 存入地址//网络ip字节序 --> 主机ip地址
const char* inet_ntop(int af,const void *src,char *dst,socklen_t size)
返回值:成功返回指向 dst的指针 失败返回空指针与此相关只能转换AF_INET ip字节序的函数
inet_addr IP地址的字符串赋值转换为in_addr类型
inet_ntoa,可以把一个in_addr类型转换为一个字符串。
5.sockaddr和sockaddr_in
sockaddr
头文件#include <sys/socket.h>中定义
sockaddr的缺点:sa_data把目标地址和端口存在一起
struct sockaddr {
sa_family_t sin_family;//地址族
char sa_data[14]; //前2字节:端口 后4字节:ip地址 后8字节作为填充
};
sockaddr_in
struct sockaddr_in{
short sin_family;//(地址族)
unsigned short sin_port;/*端口号*/
struct in_addr sin_addr;/*IP 地址*/
unsigned char sin_zero[8];/*Same size as struct sockaddr没有实际意义,只是为了 跟SOCKADDR结构在内存中对齐*/
};
我的理解:网络通信api的参数默认为sockaddr,但由于不好指定端口和ip地址,一般定义sockaddr_in 来方便赋值端口和ip地址,调用api函数时强转为sockaddr类型即可
6. 服务器端基本函数 bind listen accept
int
bind(
int
sockfd ,
const
struct
sockaddr * my_addr, socklen_t addrlen);
int listen(int fd, int backlog)
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
7. 客户端基本函数 connect
int
connect(
int
sock,
struct
sockaddr *serv_addr, socklen_t addrlen)
8.send 和 recv
int send( SOCKET s, const char *buf, int len, int flags );
int recv( SOCKET s, const char *buf, int len, int flags);
8.多线程
头文件 pthread.h
创建线程 pthread_create (与windows CreateThread 用法相似
)
int
pthread_create(pthread_t *tidp,
const
pthread_attr_t *attr,
void
*(*start_rtn)(
void
*),
void
*arg);
pthread_detach()与pthread_join
pthread_detach()即主线程与子线程分离,子线程结束后,资源自动回收。
pthread_join()即是子线程合入主线程,主线程阻塞等待子线程结束,然后回收子线程资源。
int pthread_join(pthread_t tid); 若成功则返回0,若出错则为非零。
int pthread_join(pthread_t tid); 若成功则返回0,若出错则为非零。
9.通信流程
10.多线程并发样例程序
服务器端
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<pthread.h>void * working(void *arg);struct SockInfo
{struct sockaddr_in addr;int fd;
};struct SockInfo infos[512];int main()
{//1.创建监听的套接字int fd = socket(AF_INET,SOCK_STREAM,0);if(fd==-1){perror("socket");return -1;}//2.连接本地的ip 端口struct sockaddr_in saddr;saddr.sin_family =AF_INET;saddr.sin_port = htons(9999);saddr.sin_addr.s_addr = INADDR_ANY;int ret = bind(fd,(struct sockaddr*) &saddr,sizeof(saddr));if(ret==-1){perror("bind");return -1;}//3.设置监听ret = listen(fd,128);if(ret==-1){perror("listen");return -1;}//初始化客户端数组int max = sizeof(infos)/sizeof(infos[0]);for(int i=0; i<max;i++){bzero(&infos[i],sizeof(infos[i]));infos[i].fd=-1;}//4.阻塞并等待客户端的连接while(1){struct SockInfo * pinfo;int addrlen =sizeof(sockaddr_in);for(int i=0; i<max;i++){if(infos[i].fd==-1){pinfo=&infos[i];break;}}int cfd= accept(fd,(struct sockaddr*) &pinfo->addr,&addrlen);if(cfd==-1){perror("accept");continue;}pinfo->fd=cfd;//创建子线程pthread_t tid;pthread_create(&tid,NULL,working,pinfo);phread_detach(tid);}close(fd);return 0;
}
void working(void *arg)
{//5.连接成功打印客户端信息struct SockInfo *pinfo = (struct SockInfo*) arg;char ip[32];printf("客户端ip: %s, 端口: %d\n",inet_ntop(AF_INET,&pinfo->addr.sin_addr.s_addr,ip,sizeof(ip)),ntohs(&pinfo->addr.sin_port));while(1){//接受数据char buf[1024];int len =recv(pinfo->fd,buf,sizeof(buf),0);if(len>0){printf("client say: %s",buf);send(pinfo->fd,buf,sizeof(buf),0);}else if(len==0){printf("clinet closed!\n");break;}else{perror("recv");break;}}//关闭socketclose(pinfo->fd);return NULL;
}
客户端
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>int main()
{ //1.创建通信的套接字int fd = socket(AF_INET,SOCK_STREAM,0);if(fd==-1){perror("socket");return -1;}//2.连接服务器的ip 端口struct sockaddr_in saddr;saddr.sin_family =AF_INET;saddr.sin_port = htons(9999);inet_pton(AF_INET,"121.41.88.239",&saddr.sin_addr.s_addr);int ret = connect(fd,(struct sockaddr*) &saddr,sizeof(saddr));if(ret==-1){perror("connect");return -1;}int number=0;while(1){//接受数据char buff[1024];sprintf(buff,"hello %d\n ",number++);send(fd,buff,strlen(buff)+1,0);memset(buff,0,sizeof buff);int len=recv(fd,buff,sizeof(buff),0);if(len>0){printf("server say: %s\n",buff);}else if(len==0){printf("server closed!\n");break;}else{perror("recv");break;}sleep(1);}//关闭socketclose(fd);return 0;
}
Linux网络编程基础及多线程并发案例相关推荐
- Linux网络编程基础<多进程并发服务器>
一.应用场景 最简单的socket示列代码只能一个客户端连接一个服务器,并不支持多个客户端对服务器的连接,为了能让多个客户端进行连接所以需要多进程或者多线程处理 二.思路解析 服务器端的程序是俩个套接 ...
- Linux网络编程基础知识
Linux网络编程基础知识 1. 协议的概念 1.1 什么是协议 1.2 典型协议 2 网络应用程序设计模式 2.1 C/S模式 2.2 B/S模式 2.3 优缺点 3 分层模型 3.1 OSI七层模 ...
- Linux网络编程基础1(网络应用程序设计模式,分层模型,协议格式)
Linux网络编程基础(网络应用程序设计模式,socket编程,inet_pton,inet_ntop,服务端创建连接的过程,客户端创建连接的过程,socket函数封装) 1. 网络应用程序设计模式 ...
- Linux网络编程基础和一步一步学
·Linux网络编程 基础(一) ·Linux网络编程 基础(二) ·Linux网络编程 基础(三) ·Linux网络编程 基础(四) ·Linux网络编程 基础(五) ·Linux网络编程 基础(六 ...
- Linux网络编程基础
2019独角兽企业重金招聘Python工程师标准>>> (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍 客户端和服务端 网络程序和普通的程序有一个最大的 ...
- Linux网络编程服务器模型选择之并发服务器(上)
转载:http://www.cnblogs.com/lizhenghn/p/3617666.html 与循环服务器的串行处理不同,并发服务器对服务请求并发处理.循环服务器只能够一个一个的处理客户端的请 ...
- 【Linux网络编程部分----多进程高并发poll模型】
目录 前言 背景 分析 编写步骤 服务器: 客户端: 服务器端代码 附:文件操作部分 附:目录操作部分 客户端代码 全部代码 头文件部分 服务器全部代码 客户端所有代码 总结: 前言 本文采用 Vi ...
- linux 网络编程 ping,Linux 网络编程基础(4) -- Ping 的C代码实现
1.背景 在进行网络编程的时候,通常使用的协议有TCP协议,UDP协议.这些协议在简历套接字之初需要制定套接字的类型,比如TCP应当设置为 SOCK_STREAM, UDP对应的套接字应当设置为SOC ...
- Linux高性能服务器编程 第5章 Linux网络编程基础API
5.1 socket 地址 API 现代CPU的累加器一次都能装载(至少)4 字节(这里考虑32位机,下同),即一个整 数.那么这4 字节在内存中排列的顺序将影响它被累加器装载成的整数的值.这就是字节 ...
最新文章
- SQL Date 函数
- flutter 一行代码取消 返回按钮
- linux 安装u盘win7系统安装教程,centos u盘安装 boot制作u盘win7盘工具
- 使用 Boost.Math 计算 Jacobi Zeta 函数的简单示例, 并使用相应的 WolframAlpha 命令
- Jupyter Noteboot 添加kernel 环境
- 基于springMVC拦截器实现操作日志统计
- CrudRepository/JpaRepository/PagingAndSortingRepository之间的区别
- 带你走进SAP项目实施过程——前言(0)
- php radiobutton,radiobutton怎么用
- python第七天--文件练
- 凌度行车记录仪刷机包_凌度行车记录仪怎样升级?
- 用手机玩转ContextCapture(Smart3D)跑出惊艳三维模型
- 2022年最新BIM计费标准,涉及14省市
- 租服务器的 直连100m是啥,如何知道我的服务器带宽是独享10M或者100M?
- 正睿OI补题(贪心)
- 戴尔 OptiPlex 3020重新安装win10系统的教程
- 如何使用电脑上的谷歌浏览器来调试安卓手机上的移动端页面
- NLP(八):文本表示:word2vec原理及其gensim实现
- 关于JS中的内存溢出与内存泄漏
- LeetCode 2423. Remove Letter To Equalize Frequency【哈希表】简单
热门文章
- 基于Tensorflow的英文评论二分类CNN模型
- Python3学习笔记23-StringIO和BytesIO
- 鸿蒙os将用在哪款机型,鸿蒙OS即将到来,首款机型现已确认,华为P50恐无缘
- Android Transition过渡动画
- 【独立版】智创云享3107、易搜资料1.4.3、变现宝1.2.4最新版
- 并行计算与分布式处理的区别
- SQLException: Value ‘0000-00-00 00:00:00‘ can not be represented as java.sql.Timestamp
- 【python】 安装浏览器驱动器
- Android自定义动画----蜘蛛网格图
- 2023最新帝国CMS7.5手赚网试玩平台源码/可封装APP+带文章功能系统