思路:

点对点通信,其原理也比较简单,在前面回显服务器的基础上,我们分别在服务端和客户端都使用两个线程,一个线程负责发送数据包,一个线程负责接收数据包。

代码如下:

客户端:

/*************************************************************************
> 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网络编程》之点对点通信的更多相关文章

  1. UNIX网络编程——getsockname和getpeername函数

    UNIX网络编程--getsockname和getpeername函数   来源:网络转载   http://www.educity.cn/linux/1241293.html     这两个函数或者 ...

  2. 【LINUX/UNIX网络编程】之简单多线程服务器(多人群聊系统)

    RT,Linux下使用c实现的多线程服务器.这个真是简单的不能再简单的了,有写的不好的地方,还希望大神轻拍.(>﹏<) 本学期Linux.unix网络编程的第四个作业. 先上实验要求: [ ...

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

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

  4. 【Linux/unix网络编程】之使用socket进行TCP编程

    实验一 TCP数据发送与接收 [实验目的] 1.熟练掌握套接字函数的使用方法. 2.应用套接字函数完成基本TCP通讯,实现服务器与客户端的信息交互. [实验学时] 4学时 [实验内容] 实现一个服务器 ...

  5. Unix网络编程--卷二:进程间通信

    Unix网络编程--卷二:进程间通信 本书是一部Unix网络编程的经典之作!进程间通信(IPC)几乎是所有Unix程序性能的关键,理解IPC也是理解如何开发不同主机网络应用程序的必要条件.本书从对Po ...

  6. Unix网络编程--卷一:套接字联网API

    UNIX网络编程--卷一:套接字联网API 本书面对的读者是那些希望自己编写的程序能够使用成为套接字(socket)的API进行彼此通信的人. 目录: 0.准备环境 1.简介 2.传输层:TCP.UD ...

  7. [转载] 读《UNIX网络编程 卷1:套接字联网API》

    原文: http://cstdlib.com/tech/2014/10/09/read-unix-network-programming-1/ 文章写的很清楚, 适合初学者 最近看了<UNIX网 ...

  8. UNIX网络编程

    UNIX网络编程--socket的keep http://www.68idc.cn/help/opersys/unixbsd/20150731471448.html

  9. UNIX网络编程——网络IPC:套接字

    UNIX网络编程——网络IPC:套接字 Contents 套接字接口 套接字描述符 寻址 字节序 地址格式 地址查询 绑定地址 建立连接 数据传输 套接字选项 带外数据 UNIX域套接字 使用套接字的 ...

  10. 《 UNIX网络编程》源码的使用

    学习编程这东西,看代码,改代码,运行代码这样才能学到实际东西!本书说在www.unpbook.com可以获取源码,不过打不开!所以google unpv13e.tar.gz 并在网络上找到了:源码:h ...

随机推荐

  1. 关于User&nbsp;Defined&nbsp;Runtime&nbsp;Attributes的小技巧

    在用XIB里自定制view,button,label...的一些属性时,例如边框宽度,边框颜色等,如下图:

  2. UISegmentControl 、UIStepper

    UISegmentControl .UIStepper UISegmentControl 1. UISegmentedControl *segmentControl = [[UISegmentedCo ...

  3. 认识<img>标签,为网页插入图片

    在网页的制作中为使网页炫丽美观,肯定是缺少不了图片,可以使用<img>标签来插入图片. 语法: <img src="图片地址" alt="下载失败时的替 ...

  4. JavaScript typeof, null, 和 undefined

    typeof 操作符 你可以使用 typeof 操作符来检测变量的数据类型. 实例 typeof "John"                // 返回 string typeof ...

  5. Python list 常用操作

    测试版本: python 2.7 获取第一个.最后一个元素 list1 = ["a", "b", "c"] len1 = len(list1 ...

  6. 离线安装maven

    maven离线安装 1.在eclipse根目录下新建两个文件夹,links和myplugins,myplugins文件名可以自定义 2.下载maven http://pan.baidu.com/s/1 ...

  7. winform 绘制label 中文字 - 摘

    private void label2_Paint(object sender, PaintEventArgs e) {//绘制label中文字 string text = "Sri Lan ...

  8. PartialFunction(偏函数)

    val one:PartialFunction[Int,String]={ case 1 => "one" case 2 => "two" case ...

  9. Web分析日志分析2

    http://www.docin.com/p-649515490.html http://wenku.baidu.com/link?url=kB-83fbl1Zc3Y6U2BYLj-lKMWShe8Z ...

  10. Android 手机上安装并运行 Ubuntu 12.04(转,没实测)

    设备需要root权限,并且安装了BusyBox最小 1GHz 处理器(推荐)Android 系统版本 2.1 或以上Android 设备需要自定义的ROM固件SD卡至2.5GB (安装大映像的需要3. ...