计算机网络学习socket--day3
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;
}
||---------------------------------------------------------------------
计算机网络学习socket--day3的更多相关文章
- 【总结】学习Socket编写的聊天室小程序
1.前言 在学习Socket之前,先来学习点网络相关的知识吧,自己学习过程中的一些总结,Socket是一门很高深的学问,本文只是Socket一些最基础的东西,大神请自觉绕路. 传输协议 TCP:Tra ...
- Spark菜鸟学习营Day3 RDD编程进阶
Spark菜鸟学习营Day3 RDD编程进阶 RDD代码简化 对于昨天练习的代码,我们可以从几个方面来简化: 使用fluent风格写法,可以减少对于中间变量的定义. 使用lambda表示式来替换对象写 ...
- python学习------socket编程
一 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务端为你提供视频 ...
- 在Android手机上学习socket程序
我们都知道Android手机是基于Linux系统的,在没有Linux环境,但是想学习socket编程的同学可以在Android手机中试试,利用ndk编译可执行文件在Android手机中运行.不同于动态 ...
- [转] 3个学习Socket编程的简单例子:TCP Server/Client, Select
以前都是采用ACE的编写网络应用,最近由于工作需要,需要直接只用socket接口编写CS的代码,重新学习这方面的知识,给出自己所用到的3个简单例子,都是拷贝别人的程序.如果你能完全理解这3个例子,估计 ...
- 深入学习socket网络编程,以java语言为例
了解java的socket编程与Linux Socket API之间的关系 一.java的网络编程 1.socket原理 socket通信就是通过IP和端口号将两台主机建立连接,提供通信.主机A的应用 ...
- 计算机网络学习笔记NO.2 物理层
2.1 基本概念 2.1.1 物理层概念 物理层解决如何在连接各种计算机的传输媒体上传输数据比特流,而不是指具体的传输媒体. 物理层主要任务:确定与传输媒体接口有关的一些特性(定义标准) 机械特性:定 ...
- MFC学习 socket
下面未处理异常 tcpserver.cpp #include "WinSock2.h" #include <stdio.h> #pragma comment(lib, ...
- python网络爬虫与信息提取 学习笔记day3
Day3: 只需两行代码解析html或xml信息 具体代码实现:day3_1 注意BeautifulSoup的B和S需要大写,因为python大小写敏感 import requests r ...
随机推荐
- LR脚本信息函数-lr_get_host_name
lr_get_host_name() 返回主机的名称. char * lr_get_host_name(); lr_get_host_name函数返回执行脚本的机器的名称. 示例:lr_get_hos ...
- 在IntelliJ IDEA中注释使用的说明
/** * @author 标明该类模块的开发作者 * @version 标明该类模块的版本 * @see 参开转向,也就是相关的主题 * @param 对方法中的某些参数进行说明 * @return ...
- cb25a_c++_函数对象简介
cb25a_c++_函数对象简介预定义的函数对象https://blog.csdn.net/txwtech/article/details/104382505negate<type>()p ...
- Jenkins自动化测试脚本的构建
[准备环境] 自动化测试框架脚本 Linux下的Python环境 https://www.cnblogs.com/xinhua19/p/12836522.html [思路] 测试顺序是,测试通过 ...
- 006.OpenShift持久性存储
一 持久存储 1.1 持久存储概述 默认情况下,运行容器使用容器内的临时存储.Pods由一个或多个容器组成,这些容器一起部署,共享相同的存储和其他资源,可以在任何时候创建.启动.停止或销毁.使用临时存 ...
- 3.WebPack配置文件
一.为什么需要WebPack配置文件 引用自官方: 在 webpack 4 中,可以无须任何配置使用,然而大多数项目会需要很复杂的设置,这就是为什么 webpack 仍然要支持 配置文件.这比在终端( ...
- vue 生命周期:
vue 生命周期: 1. beforeCreate()创建组件; 2. created() 创建完成; 3. beforeMounte() 组件被挂裁前; ...
- 尚硅谷spring 事物管理
接下来我们重点来学习spring中的事务管理 接下来我们通过代码来实现 spring实现事物我们采用aop的方式来实现 获得连接和手动设置事物相当于@before标注的前置通知,conn.commit ...
- nmap二层发现
使用nmap进行arp扫描要使用一个参数:-sn,该参数表明屏蔽端口扫描而只进行arp扫描. nmap支持ip段扫描,命令:nmap -sn 192.168.1.0/24 nmap速度比arping快 ...
- Spring IoC 默认标签解析
前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 本篇文章主要介绍 Spring IoC 容 ...