《UNIX网络编程》之点对点通信
思路:
点对点通信,其原理也比较简单,在前面回显服务器的基础上,我们分别在服务端和客户端都使用两个线程,一个线程负责发送数据包,一个线程负责接收数据包。
代码如下:
客户端:
/*************************************************************************
> File Name: p2pcli.c
> Author: ma6174
> Mail: ma6174@163.com
> Created Time: Sun 05 Oct 2014 09:26:40 PM HKT
************************************************************************/ #include<stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h> #include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
}while() void handler(int sig)
{
printf("recv a sigal sig = %d\n", sig);
printf("parent exit\n");
exit();
} int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr; if(argc != )
{
//printf("usage: p2pcli <IPaddress> ");
//exit(0);
ERR_EXIT("usage: p2pcli <IPaddress> ");
} sockfd = socket(AF_INET, SOCK_STREAM, ); memset(&servaddr, , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons();
servaddr.sin_addr.s_addr = inet_addr(argv[]); if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < )
{
ERR_EXIT("connect");
} pid_t pid;
pid = fork();
if(pid == -)
{
ERR_EXIT("fork");
}
else if(pid == )
{
//child
char recvbuf[] = {};
while()
{
memset(recvbuf, , sizeof(recvbuf));
int ret = read(sockfd, recvbuf, sizeof(recvbuf));
if(ret == -)
{
ERR_EXIT("read");
break;
}
else if(ret == )
{
printf("peer client close.\n");
break;
}
else
{
fputs(recvbuf, stdout);
}
}
printf("child thread exit\n");
kill(getppid(), SIGUSR1);
exit(EXIT_SUCCESS); }
else
{
signal(SIGUSR1, handler);
char sendbuf[] = {};
while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
{
//send to server.
write(sockfd, sendbuf, strlen(sendbuf));
memset(sendbuf, , sizeof(sendbuf));
}
exit(EXIT_SUCCESS);
}
//communication
return ;
}
服务端:
/*************************************************************************
> File Name: p2psrv.c
> Author: ma6174
> Mail: ma6174@163.com
> Created Time: Sun 05 Oct 2014 08:27:06 PM HKT
************************************************************************/ #include<stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h> #include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h> #define ERR_EXIT(m)\
do\
{\
perror(m);\
exit(EXIT_FAILURE);\
}while()
/**
*child thread signal exit function
**/
void handler(int sig)
{
printf("recv a signal sig=%d\n", sig);
printf("child exit\n");
exit(EXIT_SUCCESS);
} int main()
{
int listenfd;
if( (listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < )
{
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 = htonl(INADDR_ANY); //reuse address
int on = ;
if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
{
ERR_EXIT("setsockopt");
} if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < )
{
ERR_EXIT("bind");
} if(listen(listenfd, SOMAXCONN) < )
{
ERR_EXIT("listen");
} struct sockaddr_in peeraddr;
socklen_t peerlen = sizeof(peeraddr);
int connfd; if( (connfd = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < )
{
ERR_EXIT("accept");
} printf("ip=%s, port=%d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port)); pid_t pid;
pid = fork();
if(pid == -)
{
ERR_EXIT("fork");
}
else if(pid == )
{
//child
signal(SIGUSR1, handler);
char sendbuf[];
memset(sendbuf, , sizeof(sendbuf));
while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
{
write(connfd, sendbuf, strlen(sendbuf));
memset(sendbuf, , sizeof(sendbuf));
}
exit(EXIT_SUCCESS);
}
else
{
char recvbuf[];
while()
{
memset(recvbuf, , sizeof(recvbuf));
int ret = read(connfd, recvbuf, sizeof(recvbuf));
if(ret == -)
{
ERR_EXIT("read");
}
else if(ret == )
{
printf("peer client close.\n");
break;
}
else
{
fputs(recvbuf, stdout);
}
}
printf("parent exit\n");
kill(pid, SIGUSR1);
exit(EXIT_SUCCESS);
} close(connfd);
close(listenfd);
return ;
}
《UNIX网络编程》之点对点通信的更多相关文章
- UNIX网络编程——getsockname和getpeername函数
UNIX网络编程--getsockname和getpeername函数 来源:网络转载 http://www.educity.cn/linux/1241293.html 这两个函数或者 ...
- 【LINUX/UNIX网络编程】之简单多线程服务器(多人群聊系统)
RT,Linux下使用c实现的多线程服务器.这个真是简单的不能再简单的了,有写的不好的地方,还希望大神轻拍.(>﹏<) 本学期Linux.unix网络编程的第四个作业. 先上实验要求: [ ...
- 【LINUX/UNIX网络编程】之使用消息队列,信号量和命名管道实现的多进程服务器(多人群聊系统)
RT,使用消息队列,信号量和命名管道实现的多人群聊系统. 本学期Linux.unix网络编程的第三个作业. 先上实验要求: 实验三 多进程服务器 [实验目的] 1.熟练掌握进程的创建与终止方法: 2 ...
- 【Linux/unix网络编程】之使用socket进行TCP编程
实验一 TCP数据发送与接收 [实验目的] 1.熟练掌握套接字函数的使用方法. 2.应用套接字函数完成基本TCP通讯,实现服务器与客户端的信息交互. [实验学时] 4学时 [实验内容] 实现一个服务器 ...
- Unix网络编程--卷二:进程间通信
Unix网络编程--卷二:进程间通信 本书是一部Unix网络编程的经典之作!进程间通信(IPC)几乎是所有Unix程序性能的关键,理解IPC也是理解如何开发不同主机网络应用程序的必要条件.本书从对Po ...
- Unix网络编程--卷一:套接字联网API
UNIX网络编程--卷一:套接字联网API 本书面对的读者是那些希望自己编写的程序能够使用成为套接字(socket)的API进行彼此通信的人. 目录: 0.准备环境 1.简介 2.传输层:TCP.UD ...
- [转载] 读《UNIX网络编程 卷1:套接字联网API》
原文: http://cstdlib.com/tech/2014/10/09/read-unix-network-programming-1/ 文章写的很清楚, 适合初学者 最近看了<UNIX网 ...
- UNIX网络编程
UNIX网络编程--socket的keep http://www.68idc.cn/help/opersys/unixbsd/20150731471448.html
- UNIX网络编程——网络IPC:套接字
UNIX网络编程——网络IPC:套接字 Contents 套接字接口 套接字描述符 寻址 字节序 地址格式 地址查询 绑定地址 建立连接 数据传输 套接字选项 带外数据 UNIX域套接字 使用套接字的 ...
- 《 UNIX网络编程》源码的使用
学习编程这东西,看代码,改代码,运行代码这样才能学到实际东西!本书说在www.unpbook.com可以获取源码,不过打不开!所以google unpv13e.tar.gz 并在网络上找到了:源码:h ...
随机推荐
- SWT/RAP计算器
/** *2.测试 */ public class NofTest extends AbstractEntryPoint { Text text,text2; RemoteObje ...
- N3292x IBR介绍
N3292x IBR介绍 1 IBR启动流程 图1-1 IBR启动流程 CHIP_CFG[0] Mode 0 Boot from IBR Recovery Mode with crystal inpu ...
- C#委托基础
转载自 http://woshixy.blog.51cto.com/5637578/1070976 C#委托基础1——委托基础 委托和其委托的方法必须具有相同的签名.签名相同:1.参数类型 ...
- JQUERY1.9学习笔记 之基本过滤器(十) 非选择器
非选择器jQuery( ":not(selector)" ) 例:找出所有input标签为非"checked"的,并且高亮其邻居元素span. <!DOC ...
- CSS实现div居中
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- C语言基础学习运算符-基本算术运算符
C语言中用于基本算术运算的运算符有:+,-,*,%,/.这些运算符的用法和你想像到的基本无异: 加法运算符 “+”使得它两侧的值被加到一起. 减法运算符“-”用它前面的数减去后面的数. 乘法由“*”表 ...
- TFS使用小技巧
前述: TFS是微软自家的项目管理软件 link:TFS2012团队管理基本配置及基础使用方法 碰到的问题: 一.[高级—>获取特定版本] 今天做的一个项目,自己引用程序集出错,一直没找到解决方 ...
- eclipse 重构功能。
1. Rename Rename重构的功能就是重命名Java元素.虽然可以通过手动修改文件的文件名或其它Java元素的名称,但这种方式不会更新与此Java元素相关联的引用,用户必须手动查找和此Java ...
- Solr In Action 笔记(3) 之 SolrCloud基础
Solr In Action 笔记(3) 之 SolrCloud基础 在Solr中,一个索引的实例称之为Core,而在SolrCloud中,一个索引的实例称之为Shard:Shard 又分为leade ...
- hdu 4407 Sum
http://acm.hdu.edu.cn/showproblem.php?pid=4407 题意:给定初始n个数1..n,两个操作,①1 x y p 询问第x个数到第y个数中与p互质的数的和; ② ...