本文将会简单介绍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

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

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

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

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下多进程服务端客户端模型二(粘包问题与一种解决方法)

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

7、Web Service-IDEA-jaxws规范下的 服务端&sol;客户端 开发

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

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

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

c&plus;&plus; 网络编程(一)TCP&sol;UDP windows&sol;linux 下入门级socket通信 客户端与服务端交互代码

linux 进程sockfd fork,Linux下多进程服务端客户端模型一(单进程与多进程模型)...相关推荐

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

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

  2. linux进程管理fork,Linux -- 进程管理之 fork() 函数

    一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间.然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同.相当于克隆了一个自己. Test1 f ...

  3. linux进程管理机制,linux进程管理,linux进程管理机制

    linux进程管理,linux进程管理机制 一.基本介绍 1.在 LINUX 中,每个执行的程序(代码)都称为一个进程.每一个进程都分配一个 ID 号 2.每一个进程,都会对应一个父进程,而这个父进程 ...

  4. [Eureka集群] 在linux上部署SpringCloudEureka的集群服务端(Dalston.SR5版本)

    搭配使用 logback日志配置: https://blog.csdn.net/a755199443/article/details/92208902 Eureka单机服务端配置: https://b ...

  5. 如何用Linux系统搭建天堂2初章服务端

    如何用Linux系统搭建天堂2初章服务端 准备 1,一台云服务器(这里用的是免费服务器-三丰云https://www.sanfengyun.com/) 2,天堂2初章服务端(这里用的是血玫瑰天堂2论坛 ...

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

    TCP/IP网络编程之多进程服务端(一) 进程概念及应用 我们知道,监听套接字会有一个等待队列,里面存放着不同客户端的连接请求,如果有一百个客户端,每个客户端的请求处理是0.5s,第一个客户端当然不会 ...

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

    TCP/IP网络编程之多进程服务端(二) 信号处理 本章接上一章TCP/IP网络编程之多进程服务端(一),在上一章中,我们介绍了进程的创建和销毁,以及如何销毁僵尸进程.前面我们讲过,waitpid是非 ...

  8. windows环境下MySQL服务端和客户端安装,超详细

    windows环境下MySQL服务端和客户端安装,超详细 MySQL简介 MySQL的安装步骤 服务端安装 客户端安装 MySQL简介 MySQL是关系型数据库,由n张互相关联的表组成.一般是c或c+ ...

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

    TCP/IP网络编程之基于TCP的服务端/客户端(一) 理解TCP和UDP 根据数据传输方式的不同,基于网络协议的套接字一般分为TCP套接字和UDP套接字.因为TCP套接字是面向连接的,因此又称为基于 ...

最新文章

  1. 国内首个手机AR实景驾驶导航上线,还能识别车辆行人,搜狗地图出品
  2. android drawableleft 垂直居中,Android TextView前加图标垂直居中第一行(仿大众点评购买须知/提示语)...
  3. 【实战 Ids4】║ 给授权服务器加个锁——HTTPS配置
  4. webform计算某几列结果_利用DataTable.Compute等方法和属性做各种统计(某一列的总和sum、不重复的某列记录数distinct)...
  5. Java框架篇---spring aop两种配置方式
  6. 转载--json调用示例
  7. IOS 8.0 适配应用图片设计
  8. mysql修改内置函数,Mysql常见内置函数
  9. 杭电1872稳定排序
  10. java memcache 实例_Java使用memcache示例
  11. 2012第50周星期日
  12. git commit --amend两种用法
  13. 完美解决SpringMVC中静态资源无法找到(No mapping found for HTTP request with URI)问题...
  14. 【虚幻4】从U3D到UE4的转型之路
  15. 巨人史玉柱的创业故事
  16. 用友文件输出在服务器电脑,用友软件电脑怎么远程连接服务器
  17. app逆向--美图秀秀sig参数
  18. 《视觉SLAM进阶:从零开始手写VIO》(二)
  19. Arcgis学习1:arcgis下载and画一个省份
  20. 微信小程序云开发开源项目:在线提货系统

热门文章

  1. git统计提交代码量
  2. 专访李钊:技术人才转向管理属于资源浪费
  3. 你一定要用好的实用外贸工具(内附清单)
  4. UML建模工具Astah Pro教程
  5. 20172304 《程序设计与数据结构》 第二周学习总结
  6. 什么是扩散模型(Diffusion Models),为什么它们是图像生成的一大进步?
  7. 使用PWM控制来实现电压的变化控制
  8. 杂文-俞敏洪一分钟励志演讲稿
  9. Unity-3D相机跟随控制
  10. 24个Web前端人员不能错过的在线检测网站汇总