本文将会简单介绍Linux下如何利用C库函数与系统调用编写一个完整的、初级可用的C-S模型。

一、基本模型:

1.1   首先服务器调用socket()函数建立一个套接字,然后bind()端口,开始listen()监听,此时,套接字变成了被动的套接字,用于侦听客户端的请求。然后accept(),开始阻塞监听客户端的请求。

  1.2   客户端以服务端的参数为参数,用socket()建立套接字,然后connect()连接服务端。

1.3  服务端收到连接请求,accept()返回一个标识符,继续执行后面的指令。具体如图:

1.4  服务端创建套接字与绑定端口代码(打码处为点分十进制的IP字符串,注意,端口号用函数转换成网络传输的大端的Long类型,点分十进制IP转换成二进制。):

1.5 服务端监听与accept,并且循环读写代码:

while结束后close(conn)  close(sockfd)即可。

1.6 客户端(打码处为服务端的IP与端口)

二、多进程

2.1

由于accept是阻塞的函数,如果用单进程进行,那么将会只能接受一个客户端的请求。而对于其他客户端的请求,则代码不会返回去重新执行accept();

     要注意的是,其他客户端连接服务器时,即使服务器只接受一个客户端的业务请求,但是内核会帮我们完成TCP的三次握手连接,放入已连接的队列中等待服务器的accept去取走,不过,由于我们没有开启新的进程,所以,后来的这些连接没有机会被取走了。如图:

2.2

 针对以上问题,可以将accept()放入while循环中,然后每一次接收到了连接,则创建一个子进程,然后子进程去执行读写操作,而父进程则继续监听。代码如下:

 #include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h> #include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h> #include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h> int main(void)
{
int sockfd;
// 创建一个Socket
sockfd = socket(AF_INET,SOCK_STREAM,);
if(sockfd == -){
perror("error");
exit();
} ///////////////////////////////////////////////////////////
// struct sockaddr addr; // 这是一个通用结构,一般是用具体到,然后转型
struct sockaddr_in sockdata;
sockdata.sin_family = AF_INET;
sockdata.sin_port = htons();
sockdata.sin_addr.s_addr = inet_addr(我是IP字符串); int optval = ;
if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)) == -)
{
perror("error");
exit();
}
if(bind(sockfd,(struct sockaddr *)&sockdata,sizeof(sockdata)) < ){
perror("error");
exit();
} ////////////////////////////////////////////////////////////
if(listen(sockfd,) == -){
perror("error");
exit();
} //////////////////////////////////////////////////////////
struct sockaddr_in peeradr;
socklen_t peerlen = sizeof(peeradr); // 得有初始值 /////////////////////////////////////////////////////////
char recvBuff[]={};
int conn = ;
while(){
conn = accept(sockfd,(struct sockaddr *)&peeradr,&peerlen);
if(conn == -){
perror("error");
exit();
}
// 每来一个链接fork一个进程。
pid_t pid;
pid = fork(); if(pid == ){
int ret = ;
close (sockfd); // 由于子进程复制来sockfd,所以关掉它。 不干涉父进程来,因为这是一个副本。由父进程继续监听
printf("收到的IP %s\n 客户端端口是:%d\n",inet_ntoa(peeradr.sin_addr),ntohs(peeradr.sin_port));
while((ret = read(conn,recvBuff,sizeof(recvBuff))) && ret > ){
// 服务器收到打印数据,然后回发
fputs(recvBuff,stdout);
write(conn,recvBuff,ret);
}
exit();
}
else if(pid > ){
close(conn); // 父进程只管监听,不需要链接套接字!!
}
else{
perror("error");
close(conn);
close(sockfd);
exit();
}
}
close(conn);
close(sockfd);
return ;
}

server.c

而客户端没有什么变化,代码如下:

 #include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h> #include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h> #include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h> int main(void)
{
int sockfd;
// 创建一个Socket
sockfd = socket(AF_INET,SOCK_STREAM,);
if(sockfd == -){
perror("error");
exit();
} ///////////////////////////////////////////////////////////
// struct sockaddr addr; // 这是一个通用结构,一般是用具体到,然后转型
struct sockaddr_in sockdata;
sockdata.sin_family = AF_INET;
sockdata.sin_port = htons();
sockdata.sin_addr.s_addr = inet_addr("我是IP字符串");
if(connect(sockfd,(struct sockaddr *)&sockdata,sizeof(sockdata)) == -){
perror("error");
exit();
} char sendBuff[] = {};
char recvBuff[] = {}; while(fgets(sendBuff,sizeof(sendBuff),stdin) != NULL){
// 将输入到数据送到服务端
write(sockfd,sendBuff,sizeof(sendBuff));
// 从服务器读数据
read(sockfd,recvBuff,sizeof(recvBuff)); // 显示在屏幕上
fputs(recvBuff,stdout);
// 清零
memset(recvBuff,,sizeof(recvBuff));
memset(sendBuff,,sizeof(sendBuff));
} close(sockfd);
return ;
}

client.c

Linux下多进程服务端客户端模型一(单进程与多进程模型)的更多相关文章

  1. Linux下多进程服务端客户端模型二(粘包问题与一种解决方法)

    一.Linux发送网络消息的过程 (1) 应用程序调用write()将消息发送到内核中 ( 2)内核中的缓存达到了固定长度数据后,一般是SO_SNDBUF,将发送到TCP协议层 (3)IP层从TCP层 ...

  2. 7、Web Service-IDEA-jaxws规范下的 服务端/客户端 开发

    前提简介:这里之后即使基于IDEA进行开发的,风格与之前有些不同之处! 1.服务端的开发 1.创建新的项目 2.pom.xml 添加开发时所需要的依赖 <?xml version="1 ...

  3. Linux下smba服务端的搭建和客户端的使用

    解决了 windows下用root登录linuxsamba后有部分目录访问无权限的问题.应该是SELinux 设置问题. 对selinux进行修改,一般为终止这项服务,操作如下: 查看SELinux状 ...

  4. c++ 网络编程(一)TCP/UDP windows/linux 下入门级socket通信 客户端与服务端交互代码

    原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/9601511.html c++ 网络编程(一)TCP/UDP  入门级客户端与服务端交互代码 网 ...

  5. c++ 网络编程(四) LINUX/windows下 socket 基于I/O复用的服务器端代码 解决多进程服务端创建进程资源浪费问题

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9613861.html 好了,继上一篇说到多进程服务端也是有缺点的,每创建一个进程就代表大量的运 ...

  6. CentOS7下rsync服务端与Windows下cwRsync客户端实现数据同步配置方法

    最近需求想定期备份服务器d盘的数据到Linux服务器上面,做个笔记顺便写下遇到的问题 以前整过一个win下的cwrsync(客户端)+rsync(服务端:存储)的bat脚本 和整过一个Linux下的r ...

  7. TCP/IP网络编程之多进程服务端(二)

    信号处理 本章接上一章TCP/IP网络编程之多进程服务端(一),在上一章中,我们介绍了进程的创建和销毁,以及如何销毁僵尸进程.前面我们讲过,waitpid是非阻塞等待子进程销毁的函数,但有一个不好的缺 ...

  8. Linux 下Telnet 服务安装

    Linux 下Telnet 服务安装 注:以下所有命令均在root用户下执行. 命令测试在Linxu版本6.x下完成,部分命令不适用Linux 7.0以上 1.简介 默认情况下Linux只安装了Tel ...

  9. TCP/IP网络编程之基于UDP的服务端/客户端

    理解UDP 在之前学习TCP的过程中,我们还了解了TCP/IP协议栈.在四层TCP/IP模型中,传输层分为TCP和UDP这两种.数据交换过程可以分为通过TCP套接字完成的TCP方式和通过UDP套接字完 ...

随机推荐

  1. hadoop进阶

    Java 多线程安全机制 1.操作系统有两个容易混淆的概念,进程和线程. 进程:一个计算机程序的运行实例,包含了需要执行的指令:有自己的独立地址空间,包含程序内容和数据:不同进程的地址空间是互相隔离的 ...

  2. UIView和CALayer是什么关系?

    UIView显示在屏幕上归功于CALayer,通过调用drawRect方法来渲染自身的内容,调节CALayer属性可以调整UIView的外观,UIView继承自UIResponder,比起CALaye ...

  3. Linux忘记root密码的解决办法

    这里以centos6为例: 第一步:先将系统重新启动,在读秒的时候按下任意键就会出现如下图的菜单界面: 第二步:按下『e』就能够进入grub的编辑模式,如图: 第三步:将光标移动到kernel那一行, ...

  4. python3知识点之---------列表的介绍

    1.列表是什么? 它是由一系列特定顺序排序的元素组成.元素可以表示一切任何的事物,元素之间可以没有任何关系.列表用方括号[ ] 表示,元素之间由逗号隔开.   例如表示一系列数字的列表:  numbe ...

  5. python 学习分享-rabbitmq

    一.RabbitMQ 消息队列介绍 RabbitMQ也是消息队列,那RabbitMQ和之前python的Queue有什么区别么? py 消息队列: 线程 queue(同一进程下线程之间进行交互) 进程 ...

  6. markdown备忘

    文章主要(99%)参考自:markdown基本语法 这是二级标题 这是加粗的文字 这是倾斜的文字` 这是引用的内容 这是引用的内容 以下是分割线: 超链接 列表内容1 列表内容2 列表内容3 1.列表 ...

  7. 课时2:用python设计第一个游戏

    目录: 一.第一个小游戏 二.缩进 三.BIF 四.课时02课后习题及答案 ********************* 一.第一个小游戏 ********************* # p2_1.py ...

  8. 游戏开发学习ing

    创建工程 python cocos.py new HelloWorld -p com.cocos2dx.org -l cpp -d myprojects 这个命令就是运行python然后编译cos.p ...

  9. linux sort的用法

    sort -n 表示按照数字 sort -k 表示第几列 sort -t : 表示按照:来分列 sort -r  表示从大到小排列

  10. 华为手机怎么安装Google

    华为手机怎么安装google 新买了个华为荣耀九,结果安装Google Play提示gms core 步骤一 gms 安装器.应用市场已经下架了  地址:链接: 点击打开链接 密码: m63j 步骤二 ...