计算机网络学习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 ...
随机推荐
- CKA考试个人心得分享
考试相关准备: 真题:需要的私密: 网络:必须开启VPN,以便能访问国外网络,强烈建议在香港搭建相应FQ: 证件:考试需要出示含有拉丁文(英文)带照片的有效证件,相关有效证件参考(优先建议护照):ht ...
- Dubbo——SPI及自适应扩展原理
文章目录 引言 正文 一.什么是SPI? 1. Java SPI的实现 2. Dubbo SPI实现原理 由配置文件得到的猜想 SPI源码 二.自适应扩展机制 三.Dubbo IOC 总结 引言 Du ...
- vc6.0打开类向导时报错-Parsing error: Expected ";".Input Line: "解决方法
--------------------------- Microsoft Visual C++ --------------------------- Parsing error: Expecte ...
- 一分钟开始持续集成之旅系列之:Java + GWT
作者:CODING - 朱增辉 前言 Google Web Toolkit(GWT)是一个开源.免费的 Web 开发框架,通过该框架,您可以使用 Java 构建复杂.高性能的 JavaScript 应 ...
- 28_链表插入和删除算法的演示.swf
#include<stdio.h> #include<malloc.h> #include <stdio.h> #include <stdlib.h> ...
- Python3-socket模块-低级网络接口
Python3中的socket模块提供了对访问套接字(socket)的接口 socket可以理解为是一个管道,通过这个管道可以使两个不同的程序通过网络进行通信,在Python中的scoket()函数可 ...
- git和github入门指南(3.3)
3.4.开源项目的协作方式 开源项目通常是没有写入的权限的,我们需要换一种协作方式参与到这些开源项目中 为了演示方便,我们把git-demo这个项目中nd-00002这个合作者的权限取消 接下来nd- ...
- 四. sql上线平台
一.inception安装使用 inception是一个集审核.执行.备份及生成回滚语句于一身的MySQL自动化运维工具 [root@CentOS ~]# [root@CentOS ~]# wget ...
- vim中设置tab的长度
- 使用TransferLearning实现环视图像的角点检测——Tensorflow+MobileNetv2_SSD
环境说明 依赖环境安装eIQ官方指南: name: eiq_auto channels: - conda-forge - defaults dependencies: - numpy=1.18.1=p ...