1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Linux网络编程基础及多线程并发案例

Linux网络编程基础及多线程并发案例

时间:2018-09-23 11:56:09

相关推荐

Linux网络编程基础及多线程并发案例

目录

1.ip:端口 TCP/IP协议

2.socket 头文件sys/socket.h

3.字节序

4.ip地址转换函数

5.sockaddr和sockaddr_in

6.服务器端基本函数 bindlisten accept

7.客户端基本函数connect

8.send 和 recv

8.多线程

9.通信流程

10.多线程并发样例程序

1.ip:端口 TCP/IP协议

AF_INET IPv4

AF_INET6IPv6

SOCK_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_addrIP地址的字符串赋值转换为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

structsockaddr_in{

shortsin_family;//(地址族)

unsignedshortsin_port;/*端口号*/

structin_addrsin_addr;/*IP 地址*/

unsignedcharsin_zero[8];/*Samesizeasstructsockaddr没有实际意义,只是为了跟SOCKADDR结构在内存中对齐*/

};

我的理解:网络通信api的参数默认为sockaddr,但由于不好指定端口和ip地址,一般定义sockaddr_in 来方便赋值端口和ip地址,调用api函数时强转为sockaddr类型即可

6. 服务器端基本函数 bindlisten accept

intbind(intsockfd,conststructsockaddr*my_addr,socklen_taddrlen);

int listen(int fd, int backlog)

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

7. 客户端基本函数connect

intconnect(intsock,structsockaddr*serv_addr,socklen_taddrlen)

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用法相似)

intpthread_create(pthread_t*tidp,constpthread_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;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。