Linux下p2p的聊天功能实现细节

Do one thing at a time, and do well.

今天闲着没事,写一个P2P的点对点的聊天功能的小程序,我觉得对网络编程初学者的学习很有用的。二话不说,我先贴代码吧。有几个地方需要考虑清楚。我会在代码的后面写出来。代码的下载文章的末尾。

server.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>

#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while() void do_something(int conn)
{
char recvbuf[];
for(;;)
{
memset(recvbuf,,sizeof(recvbuf));
int ret = read(conn,recvbuf,sizeof(recvbuf));
if(ret == )
{
printf("client closed!\n");
break;
}
else if(ret == -)
{
ERR_EXIT("read");
}
fputs(recvbuf,stdout);
write(conn,recvbuf,ret);
}
}
void handler(int sig)
{
printf("recv a sig = %d\n",sig);
exit(EXIT_SUCCESS);
} int main()
{
int listenfd;
if((listenfd = socket(AF_INET,SOCK_STREAM,)) < )
ERR_EXIT("socket"); int on = ;
int ret = setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on) ); struct sockaddr_in servaddr;
memset(&servaddr,,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons();
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) < )
ERR_EXIT("bind"); if((listen(listenfd,SOMAXCONN)) < )//主动套接字,变成被动套接字
ERR_EXIT("listen"); struct sockaddr_in peeraddr;
socklen_t socklen = sizeof(peeraddr);
int conn;
pid_t pid;
if((conn = accept(listenfd,(struct sockaddr*)&peeraddr,&socklen)) < )// 获得到是主动套接字
ERR_EXIT("accept");
printf("ip:%s port:%d\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port)); pid = fork();
char sendbuf[] = {};
if(pid == -) ERR_EXIT("pid");
if(pid == )
{
signal(SIGUSR1,handler);
while(fgets(sendbuf,sizeof(sendbuf),stdin) != NULL)
{
write(conn,sendbuf,strlen(sendbuf));
memset(sendbuf,,sizeof(sendbuf));
}
printf("child closed\n");
exit(EXIT_SUCCESS);
}
else
{ char recvbuf[];
while()
{
memset(recvbuf,,sizeof(recvbuf));
int ret = read(conn,recvbuf,sizeof(recvbuf));
if(ret == -)
ERR_EXIT("read");
else if(ret == )
{
printf("peer close\n");
break;
}
fputs(recvbuf,stdout);
}
printf("kill parent!\n");
kill(pid,SIGUSR1);
exit(EXIT_SUCCESS);
//do_something(conn); }
close(conn);
close(listenfd);
exit();
}
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <signal.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while() void handler(int sig)
{
printf("recv a sig = %d\n",sig);
exit(EXIT_SUCCESS);
} int main(int argc,char *argv[])
{
int sockfd;
if((sockfd = socket(AF_INET,SOCK_STREAM,)) < )
ERR_EXIT("socket");
struct sockaddr_in servaddr;
memset(&servaddr,,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons();
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); if(connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) < )
ERR_EXIT("connect"); char sendbuf[] = {};
char recvbuf[] = {};
pid_t pid;
pid = fork();
if(pid == -)
ERR_EXIT("fork");
if(pid == )
{
while()
{
memset(recvbuf,,sizeof(recvbuf));
int ret = read(sockfd,recvbuf,sizeof(recvbuf));
if(ret == -)
ERR_EXIT("read");
else if (ret == )
{
printf("peer closed\n");
break;
}
fputs(recvbuf,stdout);
} printf("child close\n");
kill(pid,SIGUSR1);
exit(EXIT_SUCCESS);
}
else
{
signal(SIGUSR1,handler);
while(fgets(sendbuf,sizeof(sendbuf),stdin) != NULL)
{
write (sockfd,sendbuf,strlen(sendbuf));
memset(sendbuf,,sizeof(sendbuf));
}
printf("parent close!\n");
}
close(sockfd);
exit();
}

实现的功能很简单,但是需要注意的几个细节:

1、C和S连接以后,当S关闭后,C仍然没有关闭,我用到了信号的功能。

实现的方法:当父进程关闭的时候,子进程也关闭,当子进程关闭的时候,把父进程也关闭了。

2、一个线程用来监听,一个线程用来等待输入。那么,这是一个多线程的小程序。

  创建一个子进程。C端,子进程进程监听,父进程等待输入。S端相反。

3、信号量的问题:

  SIGUSR1:用户自定义信号量,函数handler用来杀死进程,实现退出。

程序的测试:

总结:总的来说,这个还是很简单的,也就是几个函数是否灵活应用。注意,read函数如果没有读到,就会进入阻塞,如果收到一个0,代表对方关闭了程序,则退出程序。

代码下载:GitHub

声明:水平有限,如果有什么地方写错了或者理解有误,希望广大网友指正。

Linux下p2p的聊天功能实现的更多相关文章

  1. 实现Linux下不间断聊天和退出处理

    实现Linux下不间断聊天和退出处理

  2. linux下P2P协议(BitTorrent)-libtorrent库编译,测试

    1.libtorrent 简介,下载和编译 libtorrent简介 libtorrent是功能齐全的C ++ bittorrent的p2p协议实现,专注于效率和可伸缩性.它可以在嵌入式设备和台式机上 ...

  3. linux下文件比对功能

    很想对吧两个文本有什么不同,可linux下有没有那么方便的工具,怎么办?其实也很简单:diff命令,一行搞定. 新建a.txt文件

  4. Linux下启用IP转发功能(主要针对Ubuntu的使用)

    说明:以下的操作只要在Linux下都是通用的. Linux发行版默认情况下是不开启IP转发功能的.如果架设一个Linux路由或者VPN服务就需要开启该服务. 1.通过访问sysctl的内核ipv4.i ...

  5. windows、linux 下启用mysql日志功能

    在默认情况下,mysql安装是没有启用日志管理功能的,这为后续的维护带来很多不便的地方. 查看是否启用了日志mysql>show variables like 'log_bin'; 怎样知道当前 ...

  6. 在Linux下编译带调试功能的Bochs

    在Linux下使用Bochs参考: http://wangcong.org/articles/bochs.html http://kinglaw05.blog.163.com/blog/static/ ...

  7. Linux 下 c 语言 聊天软件

    这是我学C语言写的第一个软件,是一个完整的聊天软件,里面包括客户端,和服务器端,可以互现聊天,共享文件,有聊天室等,是一个有TCP和UDP协议的聊天软件,测试过很多次在CENTOS和UBUNTU下都通 ...

  8. Linux下Apache配置HTTPS功能

    Apache配置HTTPS功能  转 https://www.cnblogs.com/liaojiafa/p/6028816.html 一.yum 安装openssl和openssl-devel,ht ...

  9. Linux下gsoap实现webservice功能

    蓝字为关键字,等号=后面为关键字值. 一.介绍 我们用的webservice是根据gsoap编译工具来实现,gSOAP的编译器能够自动的将用户定义的本地化的C或C++数据类型转变为符合XML语法的数据 ...

随机推荐

  1. jquery选择器取值和url正则匹配

    用到的简单jquery知识,简单总结一下,一是能加深自己的记忆,二是方便自己以后查看.常言道"好记性不如烂笔头",要养成常总结.常记录的好习惯.慢慢的发现jquery很有意思,很强 ...

  2. javascript ~~ 符号的使用

    其实是一种利用符号进行的类型转换,转换成数字类型 大概是这样滴: ~~true == 1 ~~false == 0 ~~"" == 0 ~~[] == 0 ~~undefined ...

  3. C#中区别多态、重载、重写的概念和语法结构

    C#中区别多态.重载.重写的概念和语法结构 重写是指重写基类的方法,在基类中的方法必须有修饰符virtual,而在子类的方法中必须指明override. 格式: 基类中: public virtual ...

  4. runnable和thread的区别

    一是写一个类继承自Thread类,然后重写里面的run方法,用start方法启动线程二是写一个类实现Runnable接口,实现里面的run方法,用new Thread(Runnable target) ...

  5. 【转】iOS- 详解文本属性Attributes

    原文: http://www.cnblogs.com/qingche/p/3574995.html?utm_source=tuicool 1.NSKernAttributeName: @10 调整字句 ...

  6. 【cogs858】磁性链

    [题目描述] 有N块编号为1~N的特殊磁石相互吸附组成一条磁性链,只有它们紧挨着时才会传递吸力,他们之间的吸力很大,如果我们要从N块相连的磁石中取出一块,那么需要消耗N-1个单位的能量,空缺处不再有吸 ...

  7. C#编程连接数据库,通过更改配置文件切换数据库功能。

           该实例主要应用情景:假如某公司用mysql当做数据库服务器,由于发现mysql数据库在运行中出现不稳定情况,针对这情况,厂家要求更换连接数据库方式,改用SQL server数据库,来满足 ...

  8. 面试后 follow up letter 分享

    分享一下最近面试外企的follow up letter. Dear Mr. Xu,     Thank you again for the time you and Mr. Guo spent wit ...

  9. Article及ArticleList模板

    HTML5滑动条: <input type="range" min="0" max="100" value="55" ...

  10. 那些年被我坑过的Python——你来我往(第九章 selectors)

    进程.线程.协程(微线程).队列的概念理解 进程进程是所有相关资源的集合,而线程是和CPU交互的最小单元进程至少包含一个线程,是主线程线程线程之间可以共享资源线程同时修改同一份数据时必须加锁,mute ...