socket api- c/s模式:服务写,客户读. IO模式:阻塞

场景:

1)客户端从服务端获取信息.

2)阻塞模式.

所以:

1)服务端,步骤,socket, addr,bind,listen, loop{accept,write,close(auto socket)},close server socket.

  1.1.服务端地址必须绑定,以提供服务.

  1.2.listen之后,每个客户端connect会导致加入服务端的listen队列的队尾.

  1.3.accpet,时,会从listen队列的队头取出客户address,内核并在服务端建立一个新的自动地址的socket,和客户端连接.

  1.4,我们利用内核建立socket,就可以向客户端发送数据.

  1.5.记得每次 accept,write,之后,必须关闭此socket,因为是阻塞模式.客户端当没有数据时,会阻塞.也就是线程会挂起,而系统会不时,唤醒这个线程.无数据再次阻塞,挂起.

    所以,如果服务端,不关闭的话,就算没有了数据,客户还是会阻塞在  这条语句,statusFlag=read(socketClientFD,buff,10);

    并不像,man 2 read.的解释那样.没有数据会返回0.

2)客户端,步骤:socket,connect ,loop(read)

  2.1 客户端直接建立socket.地址用内核默认提供的.

  2.2. peer 端,必须填写服务的地址.以便连接.

  2.3 loop读取一定的数据.因为服务端发送完数据,会主动close.所以客户端在read的时候,当没有数据,可以获得0 状态符.

缺陷:服务端,循环读取 listen 队列,非常耗费资源. 最优是,队列有插入时,应该由内核通知程序.

  :服务端采用后台线程来处理客户链接.但是并没有显示关闭此线程(应该主线程关闭后,socket关闭后,后台线程会报错,直接退出吧)

知识点:

1) inet_pton(AF_INET,"127.0.0.1",&serverAddr.sin_addr);   转换后的格式是 4个字节, 是按顺序存放,比如这里是 0x7f,0,0,1

2) serverAddr.sin_port=htons(3003); 因为系统和网络对于数值的存放顺序不同,port是2字节,所以必须用函数转换为大端字序.

3)地址应该就不用转换,因为是4个字节,而每个字节都是是单独的数值,不会有多个字节组合为一个数值的问题.刚开始,老想的头痛,应该是不用转换的.

客户端和服务端用inet_pton就好了.

暂未分析点:

至于 serverAddr.sin_addr.s_addr=htonl(INADDR_ANY); 还没有分析为什么这样写.

server:

#include <iostream>
#include <sys/socket.h>//{socket_type.h}:socket,AF_INET,SOCK_STREAM,PF_INET
#include <netdb.h>//{<netinet/in.h>}:IPPROTO_TCP
#include <sys/errno.h>
#include <string.h>
#include <stdio.h>//perror
#include <fcntl.h>
#include <unistd.h>//close.
#include <time.h>
#include <thread>

using namespace std;

typedef struct sockaddr_in SA;

void Accpetthread(int serverFD);
int main()
{
    //socket->addr->bind->listen->accept(get time)
    int serverFD;
    int intflag;

    SA serverAddr;
    bzero(&serverAddr,sizeof(serverAddr));
    serverFD=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
    if(serverFD==-1)
    {
        perror("create()");
        return -1;
    }

    serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);
    serverAddr.sin_family=AF_INET;
    serverAddr.sin_port=htons(3003);
    //serverAddr.sin_zero??

    intflag=bind(serverFD,(sockaddr*)&serverAddr,sizeof(sockaddr));
    if(intflag==-1)
    {
        perror("bind()");
        return -1;
    }

    listen(serverFD,10);//max queue?

    thread a=thread(Accpetthread,serverFD);

    a.detach();

    int cmd;
    cout<<"exist:input 88"<<endl;
    for(;;)
    {
        cin>>cmd;
        if(cmd==88)
        {
            break;
        }
    }

    close(serverFD);
    return 0;
}

void Accpetthread(int serverFD)
{

    for(;;)
    {
        int clientFD=accept(serverFD,0,0);
        char buff[]="hi,i am server";
        write(clientFD,buff,sizeof(buff));
        close(clientFD);
    }
}

client:

#include <iostream>
#include <sys/socket.h>//{socket_type.h}:socket,AF_INET,SOCK_STREAM,PF_INET
#include <netdb.h>//{<netinet/in.h>}:IPPROTO_TCP
#include <sys/errno.h>
#include <string.h>
#include <stdio.h>//perror
#include <fcntl.h>
#include <unistd.h>//close.
#include <time.h>
#include <netinet/in.h>
#include<arpa/inet.h>//INET_PTON

using namespace std;

int main()
{
    //socket->connect->read.
    int socketClientFD;
    int statusFlag;

    socketClientFD=socket(PF_INET,SOCK_STREAM,IPPROTO_IP);
    if(socketClientFD==-1)
    {
        perror("socket()");
        return -1;
    }

    struct sockaddr_in serverAddr;
    bzero(&serverAddr,sizeof(serverAddr));
    serverAddr.sin_family=AF_INET;
    inet_pton(AF_INET,"127.0.0.1",&serverAddr.sin_addr);
    serverAddr.sin_port=htons(3003);

    statusFlag=connect(socketClientFD,(sockaddr*)&serverAddr,sizeof(serverAddr));

    if(statusFlag==-1)
    {
        perror("connect()");
        return -1;
    }

    char buff[11];

    for(;;)
    {
        statusFlag=read(socketClientFD,buff,10);
        if(statusFlag>0)
        {
            buff[10]=‘\0‘;
            cout<<buff<<flush;
        }
        else if(statusFlag==0)
        {
            cout<<endl;
            break;
        }
        else
        {
            perror("read()");
            return -1;
        }
    }

    cout<<"eixist:input 88."<<endl;
    int cmd;
    while(1)
    {
        cin>>cmd;

        if(cmd==88)
        {
            close(socketClientFD);
            break;
        }
    }

    return 0;
}
时间: 2024-10-03 13:27:36

socket api- c/s模式:服务写,客户读. IO模式:阻塞的相关文章

socket api- c/s模式:服务读写,客户写读. IO模式:阻塞

服务端:socket->address->bind->listen->loop{accpet->read->write->close(auto socket)}->close(listen socket)1)因为是阻塞模式,所以客户端没有关闭的时候,服务端会阻塞在read函数,2)客户端发送之后断开连接.是一个有序的数据片.服务端由内核经过排序片.一定会接收到数据. 而不会因为close的数据先到就以为没有数据.所以必须理解客户端的行为.也就是write和c

socket api- c/s模式:服务多次读写,客户多次写读(同步处理多客户,多线程). IO模式:阻塞t

服务端: 1)多线程处理客户connect.主线程,处理用户输入,二线程处理accpet,每次有新的connect,就建立新线程处理每个客户端. 2)二线程阻塞在accept,其他新线程阻塞在read. 3)当客户端close.服务端对应线程,read得到0. 之后也进行close(这一部上次实验没做,导致服务socket一直在close wait ,而客户一直在fin wait 2.) 所以客户端socket阻塞在内核的time wait.而服务端阻塞的内核的 close wait. 缺点:

Linux统系统开发12 Socket API编程3 TCP状态转换 多路IO高并发select poll epoll udp组播 线程池

[本文谢绝转载原文来自http://990487026.blog.51cto.com] Linux统系统开发12 Socket API编程3 TCP状态转换 多路IO高并发select  poll  epoll udp组播 线程池 TCP 11种状态理解: 1,客户端正常发起关闭请求 2,客户端与服务端同时发起关闭请求 3,FIN_WAIT1直接转变TIME_WAIT 4,客户端接收来自服务器的关闭连接请求 多路IO转接服务器: select模型 poll模型 epoll模型 udp组播模型 线

Linux统系统开发11 Socket API编程2 多进程 多线程 高并发处理

[本文谢绝转载原文来自http://990487026.blog.51cto.com] <纲要> Linux统系统开发11 Socket API编程2 多进程 多线程 高并发处理 UDP服务器 客户端最小模型,处理字符转大写 TCP 多进程并发服务器模型,为每个客户端开启一个进程: TCP 多线程服务器模型,使用wrap函数封装 作业: ---------------------------------------------------- UDP服务器 客户端最小模型,处理字符转大写 [em

SOCKET API和TCP STATE的对应关系

在我们学习网络基础时,传输层的协议有TCP和UDP,在Linux网络编程中,我们使用socket API,实现网络通信. 那么:   socket API 和 TCP 协议中各个状态是如何对应的呢?我们可以通过下图来看: 在socket系统调用中,如何完成三次握手和四次挥手: SOCK_DGRAM,即UDP中的connect操作知识在内核中注册对方机器的IP和PORT信息,并没有建立链接的过程,即没有发包,close也不发包). 而SOCK_STREAM对应如下: connect会完成TCP的三

python 简单搭建非阻塞式单进程,select模式,epoll模式服务

由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 :  --> 点击这里 1 单进程服务器 - 非堵塞模式 服务端 : #coding=utf-8 from socket import * import time #用来存储所有的新连接的socket,这个是重点 g_socketList = [] def main(): serSocket = socket(AF_INET, SOCK_STREAM) serSocket.setsockopt(SO

socket API CSocket CAsyncSocket 用法及区别

要进行网络编程就要和Socket打交道,Socket有同步阻塞方式和异步非阻塞方式两种使用,事实上同步和异步在我们编程的生涯中可能遇到了很多,而Socket也没什么特别.虽然同步好用,不费劲,但不能满足一些应用场合,其效率也很低.    或许初涉编程的人不能理解"同步(或阻塞)"和"异步(或非阻塞)",其实简单两句话就能讲清楚,同步和异步往往都是针对一个函数来说的,"同步"就是函数直到其要执行的功能全部完成时才返回,而"异步"

GO网络编程和Linux Socket API的关系

先展示一下简单的go程序,然后分析GO的API和Linux API的关系.像简单的socket概念等就不在这里介绍了,不懂的去百度一下. server.go package main import "net" import "fmt" import "bufio" import "strings" // only needed below for sample processing func main() { fmt.Prin

通过基于java实现的网络聊天程序分析java中网络API和Linux Socket API关系

1. 引言 socket网络编程,可以指定不同的通信协议,在这里,我们使用TCP协议实现基于java的C/S模式下“hello/hi”网络聊天程序 2. 目标 1). 通过该网络聊天程序,了解java Socket API接口的基本用法 2). java Socket API简要介绍 3). linux socket API 简单分析 4). tcp协议的连接和终止 5). 探究java socket API 和 linux socket api之间的关系 3. linux socket API