本文将会简单介绍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. BitLocker:如何启用网络解锁

    TechNet 库Windows ServerWindows Server 2012 R2 和 Windows Server 2012服务器角色和技术安全和保护BitLockerBitLocker 中 ...

  2. Avril Lavigne : Everybody Hurts (Ver3)

    http://www.guitartabsexplorer.com/ http://www.guitartabsexplorer.com/lavigne-avril-Tabs/everybody-hu ...

  3. 使用Html5shiv.js让ie支持html5

    ie低版本不支持html5标签,可以引入一段脚本,在ie浏览器中创建html5的标签. 1,可以在网上下载html5shiv的压缩包,引入压缩版的html5shiv.min.js即可. 脚本引用要在h ...

  4. android surfaceview 入门介绍

    由于工作中需自定义控件,以前没写过. 开始时,实用view 实现了,经理说不好,担心效率低,要求每秒需要刷新10次左右. 然后,学习使用  surfaceview. 看了网上简单的Demo,找到him ...

  5. 。net可以点出属性,编译没问题,运行时就报错了。一笔记。

    项目框架是这样的. 在 domain(你可以把它理解为你的bll) ,web 2个项目工程里面都引用了一个通过nuget管理程序包,比如 xxcommon.dll web 引用了 domain ,然后 ...

  6. adb启动和关闭

    启动adb服务: cmd("adb start-server"); 关闭adb服务: cmd("adb start-server");

  7. 【转载】Unity3D研究院之IOS触摸屏手势控制镜头旋转与缩放

    前几篇文章介绍了很多Unity3D引擎自身的一些问题, 今天我们在回到IOS设备上讨论一些触摸屏幕手势,本章的目标是通过触摸iPhone屏幕手势 实现模型左右的旋转,与模型的缩放. 大家想一想模型的旋 ...

  8. Linux特殊权限位

    SUID 运行某程序时,相应进程的属主是程序文件自身的属主,而不是启动者(启动者临时获得文件属主的权限)     chmod u+s file     chmod u-s file SGID 运行某程 ...

  9. Linux中awk后面的RS, ORS, FS, OFS 含义

    转载自http://blog.csdn.net/qq416647781/article/details/40649419   一.RS 与 ORS 差在哪   我们经常会说,awk是基于行列操作文本的 ...

  10. 为啥shmem不回收 | drop_caches

    内核在哪里禁止对tmpfs中内存页的回收 mem.limit_in_bytes同样会触发shrink_zones过程! shrink_zones是代码中的直接内存回收路径 1.try_to_free_ ...