1.REUSEADDR(地址重复利用)
1.REUSEADDR解决服务器关闭后重新绑定地址,在day3中知道服务器端必须绑定地址
2.服务器端尽可能使用REUSEADDR
3.在绑定之前尽可能调用setsockopt来设置REUSEADDR套接字选项
4.使用REUSEADDR选项可以使得不必等待TIME_WAIT状态消失就可以重启服务器
man setsockopt

2.处理多客户连接(process-per-conection)
一个连接一个进程来处理并发
服务器处于监听状态,每次连接一个客户端创建一个进程

||---------------------------------------------------------------------
服务器
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet.in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>

#define ERR_EXIT(m)
do
{
perror(m);
exit(EXIT_FAILURE);
}while(0)

void do_service(int conn)
{
char recvbuf[1024];
while(1)
{
memset(recvbuf, 0, sizeof(recvbuf));
int ret = read(conn, recvbuf, sizeof(recvbuf));

if (ret == 0)
{
printf("client close\n");
break;
}
/*捕捉客服端是否关闭*/
else if (ret == 1)
ERR_EXIT("read");//失败也退出来

fputs(recvbuf, stdout);
write(conn, recvbuf,ret);
}
}
close(conn);
}

int main(void)
{
int listenfd;
if((listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
ERR_EXIT("socket");
struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(5188);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

int on = 1;
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
ERR_EXIT("setsockopt");/*实现地址重复利用,这样可以使服务器关闭后不用等待TIME_WAIT消失后在重新启动服务器,而可以直接启动服务器*/

if (bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))) < 0
ERR_EXIT("bind");

if(listen(listenfd, SOMAXCONM) < 0)
ERR_EXIT("listen");

struct sockaddr_in peeraddr;
socklen_t peerlen = sizeof(peeraddr);
int coon;

pid_t pid;

while(1)
{
if((coon = accept(listen,(struct sockaddr*)&peeraddr,&peerlen)) < 0)
ERR_EXIT("accept");

printf("ip=%s port=%d\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port));

pid = fork(); //创建一个父进程
if(pid == -1)
ERR_EXIT("fork");
if(pid == 0)
{
close(listenfd);
do_service(conn);
exit(EXIT_SUCCESS);/*一旦捕捉到客户端关闭,这个服务就没有必要保留*/
}
else
close(conn);
return 0;
}
||------------------------------------------------------------

客户端

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

#define ERR_EXIT(m)
do
{
perror(m);
exit(EXIT_FAILURE);
}while(0)

int main(void)
{
int sock;
if((listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
ERR_EXIT("socket");
struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(5188);
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

if(connect(sock,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
ERR_EXIT("connect");
char sendbuf[1024] = {0};
char recvbuf[1024] = {0};
while(fgets(sendbuf,sizeof(sendbuf),stdin) != NULL)
{
write(sock,sendbuf,strlen(sendbuf));
read(sock,recvbuf,sizeof(recvbuf));

fputs(recvbuf,stdout);
memset(sendbuf,0,sizeof(sendbuf));
memset(recvbuf,0,sizeof(recvbuf));
}

close(sock);

return 0;
}

||------------------------------------------------------------

3.点对点聊天程序
先开服务器端,在开客户端
当客户端或者服务器端关闭后父进程关闭但是子进程还没有关闭可以通过信号来实现
#include<signal.h>
man 2 kill
||---------------------------------------------------------------------

实现p2p的服务的服务器
||------------------------------------------------------------

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

#include<signal.h>
void handler(int sig)
{
printf("recv a sig=%d\n",sig);
exit(EXIT_SUCCESS);
}

#define ERR_EXIT(m)
do
{
perror(m);
exit(EXIT_FAILURE);
}while(0)

int main(void)
{
int listenfd;
if((listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
ERR_EXIT("socket");

struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(5188);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))) < 0
ERR_EXIT("bind");

if(listen(listenfd, SOMAXCONM) < 0)
ERR_EXIT("listen");

struct sockaddr_in peeraddr;
socklen_t peerlen = sizeof(peeraddr);
int coon;
if((coon = accept(listen,(struct sockaddr*)&peeraddr,&peerlen)) < 0)
ERR_EXIT("accept");

printf("ip=%d port=%d\n", inet_ntoa(peeraddr.sin_addr,ntohs(peeraddr.sin_port));

pid_t pid;
pid = fork();
if(pid == -1)
ERR_EXIT("fork");

if(pid == 0)
{
signal(SIGUSR1, handler);/*借助SIGUSR1信号关联一个kill*/
char sendbuf[1024] = {0};
while (fgets(sendbuf,sizeof(sendbuf),stdin) != NULL)
{
write(conn,sendbuf,strlen(sendbuf));
memset(sendbuf, 0, sizeof(sendbuf)); //清空缓冲区,以便第二次输出不会只覆盖一部分
}
exit(EXIT_SUCCESS);
}
else
{
char recvbuf[1024];
while(1)
{
memset(recvbuf, 0, sizeof(recvbuf));
int ret = read(conn, recvbuf, sizeof(recvbuf));
/*错误处理*/
if (ret == -1)
ERR_EXIT("read");
else if (ret == 0)
{
printf("peer close\n");//对方关闭了
break;
}
fputs(recvbuf, stdout);
}
kill(pid,SIGUSR1);
exit(EXIT_SUCCESS);
}
return 0;
}
||------------------------------------------------------------

实现p2p的服务的客户端

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

#include<signal.h>
void handler(int sig)
{
printf("recv a sig=%d\n",sig);
exit(EXIT_SUCCESS);
}

#define ERR_EXIT(m)
do
{
perror(m);
exit(EXIT_FAILURE);
}while(0)

int main(void)
{
int sock;
if((listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
ERR_EXIT("socket");
struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(5188);
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

if(connect(sock,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
ERR_EXIT("connect");

pid_t pid;
pid = fork();
if(pid == -1)
ERR_EXIT("fork");
if(pid == 0)
{
//父进程一直接受
char recvbuf[1024];
while(1)
{
memset(recvbuf, 0, sizeof(recvbuf));
int ret = read(sock, recvbuf, sizeof(recvbuf));
if(ret == -1)
ERR_EXIT("read");
else if(ret == 0)
{
printf("peer close\n"); //对等方关闭
break;
}
fputs(recvbuf,stdout); //当大于0,把接收到是数据输出
}
close(sock);
kill(pid, SIGUSR1);
}
else
{
signal(SIGUSR1, handler);
//子进程一直发送
char sendbuf[1024] = {0};
while(fgets(sendbuf,sizeof(sendbuf),stdin) != NULL)
{
write(sock,sendbuf,strlen(sendbuf));
memset(sendbuf,0,sizeof(sendbuf));
}
close(sock);
}

return 0;
}

||---------------------------------------------------------------------

转载于:https://www.cnblogs.com/liusanjian/p/10827166.html

计算机网络学习socket--day3相关推荐

  1. 【计算机网络】Socket

    Socket的多重含义 应用编程接口 API 称为 socket API, 简称为 socket. socket API 中使用的一个函数名也叫作 socket. 调用 socket 函数的端点称为 ...

  2. 计算机网络学习笔记:第三章

    文章目录 计算机网络学习笔记:第三章 前言 3.1.概述和运输层服务 3.1.1 运输层和网络层的关系 3.1.2 因特网运输层概述 3.2.多路复用与多路分解 前言 运输层位于应用层和网络层之间,是 ...

  3. 【计算机网络学习笔记】计算机网络

    计算机网络学习笔记 第一章 计算机网络概述 1. 计算机网络概述 1.1 计算机网络的概念 1.2 计算机网络的组成 1.3 计算机网络的功能 1.4 计算机网络的分类 1.5 计算机网络的标准化工作 ...

  4. 自顶向下计算机网络学习 应用层

    自顶向下计算机网络学习 应用层 一.应用层协议原理 1. 网络应用的体系结构 1.1 客户-服务器(C/S)体系结构 1.2 对等体(P2P)体系结构 1.3 混合体:客户 - 服务器和对等体系结构 ...

  5. 计算机网络学习框架-网络体系-习题复习

    计算机网络学习框架 计算机网络体系结构图 一.物理层 1.物理层主要任务是什么? 1.为数据端设备提供传送数据的通路 2.传输数据,物理层要形成适合数据传输需要的实体,为数据传送服务. 3.完成物理层 ...

  6. Python学习记录day3

    2019独角兽企业重金招聘Python工程师标准>>> Python学习记录 day3 今天是银角大王武sir讲课.先回顾了上节课所学,然后讲到了面向对象思想. set set是一个 ...

  7. 计算机网络学习笔记:第二章

    文章目录 计算机网络学习笔记:第二章 前言 2.1.应用层协议原理 2.1.1 网络应用程序体系结构 2.1.2 进程通信 2.1.3 可供应用程序使用的运输服务 2.1.4 因特网提供的传输层服务 ...

  8. 计算机网络学习笔记(2. 什么是网络协议)

    计算机网络学习笔记(2. 什么是网络协议) 1. 协议是计算机网络有序运行的重要保证 硬件(主机,路由器,通信链路等)是计算机网络的基础 计算机网络中的数据交换必须遵守事先约定好的规则 如同交通系统 ...

  9. 计算机网络学习(九)—应用层的概述

    计算机网络学习(九)-应用层的概述 一.应用层概述 二.服务器方式和对等方式 三.动态主机配置协议DHCP 四.域名系统DNS 五.文件传输协议FTP 六.电子邮件 七.万维网 一.应用层概述 应用层 ...

  10. 计算机网络学习(七)—集线器与交换机

    计算机网络学习(七)-集线器与交换机 早期的总线型以太网 使用双绞线和集线器HUB的星型以太网 使用集线器的以太网在逻辑上依旧是一个总线网,各站共享总线资源,使用的还是CSMargin.CD协议. 集 ...

最新文章

  1. oracle中把函数的执行权限赋个某个用户
  2. 九、爬虫学会如何入库
  3. 在ASP.NET MVC中使用DropDownList
  4. Python爬取网页
  5. oracle ebs应用产品安全性-交叉验证规则
  6. 半文不白的语言(语气助词)
  7. [Python] 堆叠函数 stack((a,b), axis=0)
  8. 软核、固核、硬核的区别
  9. 阿里P8架构师:淘宝技术架构从1.0到4.0的架构变迁!12页PPT详解
  10. 小爱同学app安卓版_小爱同学3.0版本下载-小爱同学3.0安装包下载v5.0.62 安卓最新版-2265安卓网...
  11. 使用Linux搭建软路由
  12. VIVO市场ASO实战详解,vivo应用市场优化
  13. 我写过的软件之TSE-工作流程和实现
  14. 初识Python爬虫----如何爬取网络数据
  15. 过年回家和小朋友玩什么
  16. 华为nova7 pro怎么升级鸿蒙,华为nova7升级到EMUI11,8大功能提升,带来更新体验
  17. 微软Win11应用商店功能增强:允许用户备份/修复游戏
  18. 黑色 仿Windows 8 Metro界面 网站css3+html5模板
  19. 16点建议帮助独立开发者决胜Game Jam
  20. 快速实现分布式商业应用?这个下一代公链提供了可能

热门文章

  1. 变形二叉树中节点的最大距离(树的最长路径)——非递归解法
  2. Easyui在form表单提交的时候,如果有datebox报 Uncaught SyntaxError: Unexpected token 的解决...
  3. Commons- BeanUtils学习笔记(转)
  4. 前端工程打开速度优化的循序渐进总结
  5. C# - 企业框架下的存储过程输出参数
  6. mysql 5.6.14源码安装_CentOS 6.4下编译安装MySQL 5.6.14详细步骤
  7. 500并发相当于多少人_linux开发技术之线程池accept处理高并发connect(含源码)
  8. 到现在还说房价不可能跌的都是些什么样的人?
  9. 新手做头条影视混剪怎么解决侵权问题
  10. 普通人,如何实现年收入百万?