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的更多相关文章

  1. 【总结】学习Socket编写的聊天室小程序

    1.前言 在学习Socket之前,先来学习点网络相关的知识吧,自己学习过程中的一些总结,Socket是一门很高深的学问,本文只是Socket一些最基础的东西,大神请自觉绕路. 传输协议 TCP:Tra ...

  2. Spark菜鸟学习营Day3 RDD编程进阶

    Spark菜鸟学习营Day3 RDD编程进阶 RDD代码简化 对于昨天练习的代码,我们可以从几个方面来简化: 使用fluent风格写法,可以减少对于中间变量的定义. 使用lambda表示式来替换对象写 ...

  3. python学习------socket编程

    一 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务端为你提供视频 ...

  4. 在Android手机上学习socket程序

    我们都知道Android手机是基于Linux系统的,在没有Linux环境,但是想学习socket编程的同学可以在Android手机中试试,利用ndk编译可执行文件在Android手机中运行.不同于动态 ...

  5. [转] 3个学习Socket编程的简单例子:TCP Server/Client, Select

    以前都是采用ACE的编写网络应用,最近由于工作需要,需要直接只用socket接口编写CS的代码,重新学习这方面的知识,给出自己所用到的3个简单例子,都是拷贝别人的程序.如果你能完全理解这3个例子,估计 ...

  6. 深入学习socket网络编程,以java语言为例

    了解java的socket编程与Linux Socket API之间的关系 一.java的网络编程 1.socket原理 socket通信就是通过IP和端口号将两台主机建立连接,提供通信.主机A的应用 ...

  7. 计算机网络学习笔记NO.2 物理层

    2.1 基本概念 2.1.1 物理层概念 物理层解决如何在连接各种计算机的传输媒体上传输数据比特流,而不是指具体的传输媒体. 物理层主要任务:确定与传输媒体接口有关的一些特性(定义标准) 机械特性:定 ...

  8. MFC学习 socket

    下面未处理异常 tcpserver.cpp #include "WinSock2.h" #include <stdio.h> #pragma comment(lib, ...

  9. python网络爬虫与信息提取 学习笔记day3

    Day3: 只需两行代码解析html或xml信息    具体代码实现:day3_1    注意BeautifulSoup的B和S需要大写,因为python大小写敏感 import requests r ...

随机推荐

  1. spring boot admin 源码包的编译

    https://github.com/codecentric/spring-boot-admin 下载地址: 编译要求: Build Requirements: Node.js v8.x (LTS) ...

  2. jni不通过线程c回调java的函数 --总结

    1.JNIEnv类型是一个指向全部JNI方法的指针.该指针只在创建它的线程有效,不能跨线程传递 2.JavaVM是虚拟机在JNI中的表示,一个JVM中只有一个JavaVM对象,这个对象是线程共享的. ...

  3. 8、struct2解决中文乱码的方式

    首先建立一个jsp页面 列如 页面编码统一问题,这个最容易解决. <%@ page language="java" import="java.util.*" ...

  4. disruptor架构三 使用场景更加复杂的场景

    先c1和c2并行消费生产者产生的数据,然后c3再消费该数据 我们来使用代码实现:我们可以使用Disruptor实例来实现,也可以不用产生Disruptor实例,直接调用RingBuffer的api来实 ...

  5. Redhat FreeIPA Server 安装服务端和客户端 (实验:VMware环境下)

    实验环境:windows7 + vmware 15 + redhat 71:准备2台虚拟机:      虚拟机VMnet8,Subnet IP:192.168.145.0      Redhat 7( ...

  6. Alink漫谈(八) : 二分类评估 AUC、K-S、PRC、Precision、Recall、LiftChart 如何实现

    Alink漫谈(八) : 二分类评估 AUC.K-S.PRC.Precision.Recall.LiftChart 如何实现 目录 Alink漫谈(八) : 二分类评估 AUC.K-S.PRC.Pre ...

  7. Spring IoC 循环依赖的处理

    前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 本篇文章主要介绍 Spring IoC 是 ...

  8. 从零开始实现ASP.NET Core MVC的插件式开发(八) - Razor视图相关问题及解决方案

    标题:从零开始实现ASP.NET Core MVC的插件式开发(八) - Razor视图相关问题及解决方案 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun ...

  9. CSS DIV中表格居中显示

    将div的text-align设为center,然后将table的margin设为auto,即: <div> <table style="margin:auto; widt ...

  10. Nginx 从入门到放弃(四)

    前面我们学习了nginx的基本操作和日志管理,今天我们学习一下生产环境经常会用到的路由定位location设置,在工作中,经常可能会出现怎么设置的路由访问不到网页呀?总是出现404错误啊,这些都很有可 ...