客户端未解决Bug:子进程或者父进程退出的时候,我无法做到两个进程都调用clt_socket_Destory()方式释放socket句柄,
但是进程退出后,相应的资源也会释放,有一定影响,但是不大,以后我想到办法再优化。
重点:客户端connect服务器方法需要单独分离出来,方便用户自己断线重连。
客户端
//clthelp.h
#include <stdio.h>
#include "commsocket.h" #ifndef _vxclt
#define _vxclt #ifdef __cplusplus
extern "C"
{
#endif /**
* clientsock_init - 初始化socket
* @handle:socket句柄
* 成功返回0,失败返回错误码
* */
int clientsock_init(void **handle); /**
* connect_server - 客户端创建连接
* @handle:socket句柄
* @port:端口号
* @ipaddr:请求服务器的IP地址
* 成功返回0,失败返回错误码
* */
int connect_server(void *handle, int port, char *ipaddr,
unsigned int wait_seconds); /**
* clt_Process_business - 客户端业务处理
* @handle:socket句柄
* */
void clt_Process_business(void *handle); /**
* clt_socket_Destory - 释放socket句柄
* @handle:socket句柄
* */
void clt_socket_Destory(void **handle); #ifdef __cplusplus
extern "C"
}
#endif
#endif
//clthelp.c    --客户端代码实现
#include "clthelp.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h> /**
* clientsock_init - 初始化socket
* @handle:socket句柄
* 成功返回0,失败返回错误码
* */
int clientsock_init(void **handle)
{
int ret = ;
//初始化socket环境
//创建socket套接字
if (handle == NULL)
{
ret = Sck_ParamErr;
printf("clientsock_init() params not correct !\n");
return ret;
}
Mysock *mysock = (Mysock *) malloc(sizeof(Mysock));
if (mysock == NULL)
{
ret = Sck_MacErr;
printf("malloc() failed !");
return ret;
}
int sockfd = socket(AF_INET, SOCK_STREAM, );
if (sockfd == -)
{
ret = Sck_BaseErr;
perror("socket() err");
return ret;
}
mysock->fd = sockfd;
*handle=mysock;
return ;
} /**
* connect_server - 客户端创建连接
* @handle:socket句柄
* @port:端口号
* @ipaddr:请求服务器的IP地址
* 成功返回0,失败返回错误码
* */
int connect_server(void *handle, int port, char *ipaddr,
unsigned int wait_seconds)
{
int ret = ;
if (handle == NULL || ipaddr == NULL || port < || port > )
{
ret = Sck_ParamErr;
printf("getconnection() params not correct !\n");
return ret;
}
Mysock *mysock = (Mysock *) handle;
//connect
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ipaddr);
ret = connect_timeout(mysock->fd, &addr, wait_seconds);
if (ret == -)
{
if (errno == ETIMEDOUT)
{
//超时处理
ret = Sck_TimeoutErr;
printf("connect_timeout() time out !\n");
return ret;
}
ret = Sck_BaseErr;
perror("connect_timeout() err");
return ret;
}
return ret;
} /**
* clt_send - 客户端发送数据
* @handle:socket句柄
* @wait_seconds:等待超时秒数,如果为0表示不检测超时
* 失败返回错误码
* */
void clt_send(void *handle, unsigned int wait_seconds)
{
int ret = ;
char buf[MAXBUFSIZE] = { };
Mysock *mysock = (Mysock *) handle;
//从终端读取数据
while (fgets(buf, MAXBUFSIZE, stdin) != NULL)
{
if (strlen(buf) > MAXBUFSIZE)
{
printf("输入字节数过长!\n");
break;
}
//超时检测
ret = write_timeout(mysock->fd, wait_seconds);
if (ret == -)
{
if (errno == ETIMEDOUT)
{
printf("write_timeout() time out !\n");
break;
}
perror("write_timeout() err");
break;
} else
{
ret = socket_send(mysock->fd, buf, strlen(buf));
if (ret == -)
{
printf("socket_send() failed !\n");
break;
}
memset(buf, , MAXBUFSIZE);
}
}
} /**
* clt_recv - 客户端接收数据
* @handle:socket句柄
* @wait_seconds:等待超时秒数,如果为0表示不检测超时
* */
void clt_recv(void *handle, unsigned int wait_seconds)
{
int ret = ;
char buf[MAXBUFSIZE] = { };
int len = MAXBUFSIZE;
Mysock *mysock = (Mysock *) handle;
while ()
{
//超时检测
ret = read_timeout(mysock->fd, wait_seconds);
if (ret == -)
{
if (errno == ETIMEDOUT)
{
printf("read_timeout() time out !\n");
break;
}
perror("read_timeout() err");
break;
} else
{
len = MAXBUFSIZE;
ret = socket_recv(mysock->fd, buf, &len);
if (ret == -)
{
break;
}
fputs(buf, stdout);
memset(buf, , sizeof(buf));
}
}
} /**
* handler - 信号捕捉函数
* @sign:信号码
* */
void handler(int sign)
{
if (sign == SIGCHLD)
{
int mypid = ;
while ((mypid = waitpid(-, NULL, WNOHANG)) > )
{
printf("子进程的pid=%d\n", mypid);
}
//退出父进程
exit();
} else if (sign == SIGPIPE)
{
printf("accept SIGPIPE !\n");
} else if (sign == SIGUSR1)
{
//父进程退出,子进程也需要退出
exit();
}
} /**
* clt_Process_business - 客户端业务处理
* @handle:socket句柄
* */
void clt_Process_business(void *handle)
{
int ret = ;
if (handle == NULL)
{
ret = Sck_ParamErr;
printf("Process_business() params not correct !\n");
return;
}
//信号安装
int signoarr[] = { SIGCHLD, SIGPIPE, SIGUSR1 };
ret = Install_Signal(signoarr, , handler);
if (ret != )
{
return;
}
pid_t pid = fork();
if (pid == -)
{
ret = Sck_BaseErr;
perror("fork() err");
return;
}
if (pid == )
{
//子进程接收数据
clt_recv(handle, );
exit();
} else if (pid > )
{
//父进程写数据
clt_send(handle, );
//向子进程发信号--就算发送出错,我也毫无办法去关闭子进程了
kill(pid, SIGUSR1);
exit();
}
return;
} /**
* clt_socket_Destory - 释放socket句柄
* @handle:socket句柄
* */
void clt_socket_Destory(void **handle)
{
if (handle == NULL)
{
printf("clt_socket_Destory() param not correct !\n");
return;
}
Mysock *mysock = (Mysock *) *handle;
if (mysock != NULL)
{
printf("客户端执行释放函数!\n");
free(mysock);
*handle = NULL;
}
mysock = NULL;
}
//客户端
#include "clthelp.h" int main()
{
void *handle = NULL;
int ret = ;
//初始化socket
ret = clientsock_init(&handle);
if (ret != )
{
printf("error message:%s\n", strsockerr(ret));
return -;
}
//连接服务器
ret = connect_server(handle, , "127.0.0.1", );
if (ret != )
{
printf("error message:%s\n", strsockerr(ret));
return -;
}
//多进程发送接收信息
clt_Process_business(handle);
//释放内存
clt_socket_Destory(&handle);
return ;
}

Linux socket多进程服务器框架二的更多相关文章

  1. Linux socket多进程服务器框架一

    重点:socket共用方法中错误码的定义以及错误码的解析 底层辅助代码 //serhelp.h #ifndef _vxser #define _vxser #ifdef __cplusplus ext ...

  2. Linux socket多进程服务器框架三

    在使用select管理服务器连接的时候: 注意1:select是可中断睡眠函数,需要屏蔽信号 注意2:必须获取select的返回值nread,每次处理完一个事件,nread需要-1 注意3:如果客户端 ...

  3. linux socket高性能服务器处理框架

    这个博客很多东西 http://blog.csdn.net/luozhonghua2014/article/details/37041765   思考一种高性能的服务器处理框架 1.首先需要一个内存池 ...

  4. workerman是一个高性能的PHP socket服务器框架

    workerman-chatorkerman是一款纯PHP开发的开源高性能的PHP socket服务器框架.被广泛的用于手机app.手游服务端.网络游戏服务器.聊天室服务器.硬件通讯服务器.智能家居. ...

  5. PHP socket 服务器框架集

    1.Swoole:重新定义PHP PHP语言的高性能网络通信框架,提供了PHP语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,数据库连接池,AsyncTask,消息队列,毫秒定时 ...

  6. [C++]Linux之多进程运行代码框架

    声明:如需引用或者摘抄本博文源码或者其文章的,请在显著处注明,来源于本博文/作者,以示尊重劳动成果,助力开源精神.也欢迎大家一起探讨,交流,以共同进步- 0.0  多进程代码框架示例 /* @url: ...

  7. 【LINUX/UNIX网络编程】之使用消息队列,信号量和命名管道实现的多进程服务器(多人群聊系统)

    RT,使用消息队列,信号量和命名管道实现的多人群聊系统. 本学期Linux.unix网络编程的第三个作业. 先上实验要求: 实验三  多进程服务器 [实验目的] 1.熟练掌握进程的创建与终止方法: 2 ...

  8. 可扩展多线程异步Socket服务器框架EMTASS 2.0 续

    转载自Csdn:http://blog.csdn.net/hulihui/article/details/3158613 (原创文章,转载请注明来源:http://blog.csdn.net/huli ...

  9. 可扩展多线程异步Socket服务器框架EMTASS 2.0

    0 前言 >>[前言].[第1节].[第2节].[第3节].[第4节].[第5节].[第6节] 在程序设计与实际应用中,Socket数据包接收服务器够得上一个经典问题了:需要计算机与网络编 ...

随机推荐

  1. 转载:jsp中jstl标签的类似 if - else 语句 的语法

    原文链接:http://www.cnblogs.com/wanggd/archive/2013/05/27/3101788.html 在jsp中引入jstl的标签库和函数库 <%@ taglib ...

  2. 学习 jsonp

    1.起因 js脚本做ajax异步调用的时候,直接请求普通文件存在跨域无权限访问的问题,不管你是静态页面.动态网页.web服务,只要是跨域请求,都无法成功: 如果上句话没明白,我们直接看例子.有两个一模 ...

  3. 1.10 基础知识——GP3.1 制度化 & GP3.2 收集改进信息

    摘要: GP3.1是要求建立组织级的关于该过程的制度.标准.模版等全套体系,要求覆盖该PA所有的SP和GP.GP3.2 体现的是持续改进,每个过程都应该收集相应的改进信息. 正文: GP3.1 Est ...

  4. Redis客户端开发包:Jedis学习-入门

    添加Jedis依赖 我们可以使用以下三种方式来添加Jedis依赖. 1.下载jar文件 从http://search.maven.org/下载最近的jedis包和Apache Commons Pool ...

  5. Windows下好用到必须开机自启的小工具

    折腾过linux,黑苹果,最后还是回到了盖茨大叔的windows.得出的结论是,日常使用的话,折腾Linux还不如把精力去拿去折腾windows.分享下折腾的成果,介绍下一些很不错的小工具.     ...

  6. UNABLE TO PURGE A RECORD(二)

    上一篇文章说明了bug出现的原因和原理分析,要修复bug似乎已经水到渠成了,但远没有这么简单,只因为“并发”.要修复问题,首先要做的第一件事情是稳定的复现问题.由于数据库系统是一个并发系统,并且这个b ...

  7. 如何配置使用 Log4j

    最近在用Java 写一个FTP上传下载文件工具,正好需要产生操作日志. 利用Log4j.jar可以轻松解决.下面介绍一下Log4j的使用,具体概念到官网查阅: -------------------- ...

  8. 烂泥:KVM、kickstart与nginx集成

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 前几篇文章介绍了FTP.NFS与KVM.kickstart集成的案例,从这篇文章开始,我们来介绍HTTP方式与KVM.kickstart集成. HTTP ...

  9. mongo日志切割脚本

    两种mongo日志切割脚本 vim /etc/logrotate.d/mongodb /home/mongodb/mongolog/mongod.log { daily rotate 7 compre ...

  10. TCP/UDP常见端口参考

    著名端口 端口号码 / 层 名称 注释 1 tcpmux TCP 端口服务多路复用 5 rje 远程作业入口 7 echo Echo 服务 9 discard 用于连接测试的空服务 11 systat ...