博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux网络编程之[基于socket通信的tcp协议的编程模型]
阅读量:3749 次
发布时间:2019-05-22

本文共 6693 字,大约阅读时间需要 22 分钟。

Linux网络编程之[基于socket通信的tcp协议的编程模型]

  1. TCP客户端服务器的编程模型(傻瓜式通信流程)
  2. TCP协议的相关函数
    3 基于TCP协议的案例

TCP客户端服务器的编程模型(傻瓜式通信流程)

客户端的调用序列:    调用socket函数创建套接字    调用connect连接服务器端    调用I/O函数(read/write)函数与服务器端进行通讯    调用close关闭套接字服务器端调用序列    调用socket函数创建套接字    调用bind绑定本地地址和端口    调用listen启动监听    调用accept从已连接队列中提取客户连接    调用(I/O)函数(read/write)与客户端进行通讯    调用close关闭套接字

TCP协议的相关函数

绑定地址

#include
int bind(int sockfd,const struct sockaddr * addr,socklen_t len); 返回:成功返回0,出错返回-1 一台主机往往有多个网络接口和多个IP地址, 如果我们只去关心某个地址的连接请求, 我们可以指定一个具体的本地IP地址,如果要想用所有接口上的连接请求,就要使用一个特殊的INADDR_ANY #define INADDR_ANY (uint32_t)0x00000000 //监听所有服务器上ip得到的连接请求 struct sockaddr_in servaddr; memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_addr.s_addr = INADDR_ANY

查找绑定到套接字的地址

#include
int getsockname(int sockfd,struct sockaddr * restrict addr,socklen_t * restrict alenp); 返回:成功返回0,失败返回-1

获取对方地址

#include
int getpeername(int sockfd,struct sockaddr *restrict addr,socklen_t * restrict alenp); 返回:成功返回0,失败返回-1

服务器端

#include
int listen(int sockfd,int backlog);返回:成功返回0,失败返回-1,backlog指定进行客户端连接排队的队列长度int accept(int sockfd,struct sockaddr * restrict addr,socklen_t *restrict len);addr :客户端连接上来的时候的地址信息sockfd:传过来的sock的文件描述符

客户端

#include
int connect(int sockfd,const struct sockaddr * addr,socklen_t len);返回:成功返回0,失败返回-1

基于TCP协议的案例

/* * =========================================================================== * *       Filename:  socket_utils.h *    Description:   *        Version:  1.0 *        Created:  2017年04月23日 11时26分40秒 *       Revision:  none *       Compiler:  gcc *         Author:   (),  *        Company:   * * =========================================================================== */#ifndef __SOCKET_UTILS_H_#define __SOCKET_UTILS_H_extern void readSocketAddr(struct sockaddr_in *addr);extern void readSocket(int socketfd);extern void writeSocket(int socketfd);#endif
/* * =========================================================================== * *       Filename:  socket_utils.c *    Description:   *        Version:  1.0 *        Created:  2017年04月23日 11时28分45秒 *       Revision:  none *       Compiler:  gcc *         Author:   (),  *        Company:   * * =========================================================================== */#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//注意自定义的头文件需要放在系统的头文件之后#include"socket_utils.h"/* * *读取连接过来的客户端地址的信息 * */extern void readSocketAddr(struct sockaddr_in *addr){ //将网络字节序转换成本地字节序 int port = ntohs(addr->sin_port); char ip[16]; memset(ip,0,sizeof(ip)); //将ip地址从网络字节序转换成点分十进制形式 inet_ntop(AF_INET,&addr->sin_addr.s_addr,ip,sizeof(ip)); printf("client:%s(%d) connected\n",ip,port);}/* * *向对应的socket描述符中去读取数据 * */extern void readSocket(int socketfd){ char buffer[1024]; memset(buffer,0,1024); ssize_t size; if((size= read(socketfd,buffer,sizeof(buffer))) < 0){ perror("read error\n"); exit(1); } if(write(STDOUT_FILENO,buffer,size) != size){ perror("write error"); exit(1); }}/* * *向对应的socket描述符中去写数据 * */void writeSocket(int socketfd){ time_t t = time(0); char *s = ctime(&t); size_t size = strlen(s) * sizeof(char); //char result[] = "server connected success\n"; //连接成功后会先给客户端返回一个时间 if(write(socketfd,s,size) != size){ perror("write error\n"); exit(1); }}
/* * =========================================================================== * *       Filename:  server.c *    Description:  TCP的server端的开发 *        Version:  1.0 *        Created:  2017年04月22日 22时46分58秒 *       Revision:  none *       Compiler:  gcc *         Author:   (),  *        Company:   * * =========================================================================== */#include
#include
#include
#include
#include
#include
#include
#include
#include"socket_utils.h"//创建socket的描述符号int sockfd;void sig_handler(int sig){ if(sig ==SIGINT){ printf("server close\n"); close(sockfd); exit(1); }}int main(int argc,char *argv[]){ //从参数中传入端口号 if(argc < 2){ printf("参数不齐"); exit(1); } if(signal(SIGINT,sig_handler) == SIG_ERR){ perror("signal sigint error"); exit(1); } /* * *步骤一:创建socket,TCP协议是sock_strem(创建在内核中的) * */ sockfd = socket(AF_INET,SOCK_STREAM,0); if(sockfd < 0){ perror("socket create error\n"); exit(0); } /* * *配置socket的参数,绑定ip和端口 * */ struct sockaddr_in addr_in; memset(&addr_in,0,sizeof(addr_in)); addr_in.sin_family = AF_INET;//IP_V4 addr_in.sin_port = htons(atoi(argv[1]));//将本地字节序号转化成网络字节序号 addr_in.sin_addr.s_addr = INADDR_ANY;//服务器端监听所有服务器上ip得到的连接请求,转换成同时也是需要将其转换成网络字节序 if(bind(sockfd,(struct sockaddr*)&addr_in,sizeof(addr_in)) < 0){ perror("bind error\n"); exit(1); } /* * *启动对listen监听,通知系统去接受来自客户端的连接请求操作 *将接受到的客户端连接请求放置到对应的队列中去 * */ if(listen(sockfd,100) < 0){ perror("listen error\n"); exit(1); } /** * 使用while死循环来让server端一直等待客户端的连接,并且从连接队列中提取客户连接 */ struct sockaddr_in clientaddr; memset(&clientaddr,0,sizeof(clientaddr)); socklen_t len = sizeof(clientaddr); while(1){ //拿到客户端的sock描述符好,读写操作 int clientfd = accept(sockfd,(struct sockaddr*)&clientaddr,&len); if(clientfd < 0){ perror("recieve clientfd error"); continue; } readSocketAddr(&clientaddr); readSocket(clientfd); writeSocket(clientfd); } return 0;}
/* * =========================================================================== * *       Filename:  tcp_client.c *    Description:   *        Version:  1.0 *        Created:  2017年04月23日 12时49分30秒 *       Revision:  none *       Compiler:  gcc *         Author:   (),  *        Company:   * * =========================================================================== */#include
#include
#include
#include
#include
#include
#include
#include"socket_utils.h"int main(int argc,char * argv[]){ if(argc < 3){ perror("缺少参数"); exit(1); } /* * *创建socket * */ int clientsockfd = socket(AF_INET,SOCK_STREAM,0); if(clientsockfd < 0){ perror("socket error"); exit(1); } /* * *往serveraddr中填入ip,port和地址族类型(ipv4)connect的过程 * */ struct sockaddr_in socketaddr; memset(&socketaddr,0,sizeof(socketaddr)); socketaddr.sin_family = AF_INET; socketaddr.sin_port = htons((short)atoi(argv[2])); if(inet_pton(AF_INET,argv[1],&socketaddr.sin_addr.s_addr) <= 0){ perror("pton change error\n"); exit(1); } if(connect(clientsockfd,(struct sockaddr*)&socketaddr,sizeof(socketaddr)) < 0){ perror("connect error"); exit(1); } /* * *调用IO函数(read/write)和服务器端进行双向通信 * */ //readSocket(clientsockfd); close(clientsockfd); return 0;}

以上的代码都是可以直接进行run的,这只是一个单连接的小demo,如果server端支持多端连接的并且分别通信的话,需要加入线程等操作.在这里就没有展示了,相对于java中的socket调用,在C上显得稍微复杂了点,但是原理上其实都是一样的

转载地址:http://tzbsn.baihongyu.com/

你可能感兴趣的文章
一、算法基础+递归算法+查找算法
查看>>
走进算法工程师(算法工程师开发修炼之路)
查看>>
我与2021有个约
查看>>
100多个免费API接口分享 调用完全不限次数,以后总用得着
查看>>
leetcode每日一题【509. 斐波那契数】
查看>>
leetcode每日一题【830. 较大分组的位置】
查看>>
图灵测试过时了?
查看>>
leetcode每日一题【399. 除法求值】==》并查集&模板
查看>>
二、数据结构基础+栈+队列+迷宫问题
查看>>
python_多态
查看>>
项目:python3实现选课系统(超级详解,已完结)
查看>>
方法论:面向对象的软件工程
查看>>
python_面向对象高级——元类
查看>>
python_网络编程初探(cs架构+TCP协议)
查看>>
数据分析之Numpy
查看>>
第一门课 神经网络和深度学习(Neural Networks and Deep Learning)
查看>>
python_并发编程初探(进程篇)
查看>>
做一朵奔涌的浪花,铁马冰河不辞远
查看>>
口罩分配
查看>>
年龄巧合
查看>>