`

tcp通信事例

    博客分类:
  • C++
 
阅读更多

(转自)http://blog.csdn.net/kesaihao862/article/details/7352406

这里我们用前面所介绍的基础知识编写一个完整的TCP客户服务器程序示例。我们要实现的是一个回射服务器:
1)客户从标准输入读入一行文本,并发送给服务器
2)服务器从网络输入读入这行文本,并回射给客户
3)客户接受到回射文本后,将其显示在标准输出上。

tcp服务器源码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>

#define    SERV_PORT    5678
#define MAX_LINE    1024


void str_echo(int sockfd)
{
    ssize_t n;
    char buf[MAX_LINE] = {0};
    while( (= read(sockfd, buf, MAX_LINE)) > 0)
        write(sockfd, buf, n);
    if( n < 0)
        printf("read error.\n");
}

int main(int argc, char **argv)
{
    int listenfd, connfd;
    pid_t    childpid;
    socklen_t    cli_len;
    struct sockaddr_in    cliaddr,servaddr;
    
    cli_len = sizeof(cliaddr);
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if(listenfd < 0)
    {
        printf("create socket error!\n");
        exit(1);
    }
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);
    if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
    {
        printf("bind error!\n");
        exit(1);
    }
    listen(listenfd, 5);
    for(;;)
    {
        connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &cli_len);
        if( (childpid = fork()) == 0)/*child process*/
        {
            close(listenfd);
            str_echo(connfd);
            exit(0);
        }
        close(connfd);    /*parent close connected socket*/
    }
    return 0;
}

tcp客户端源码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>

#define    SERV_PORT    5678
#define MAX_LINE    1024


void str_cli(FILE *fp, int sockfd)
{
    char sendline[MAX_LINE], recvline[MAX_LINE];
    int n;
    while( fgets(sendline, MAX_LINE, fp) != NULL)
    {
        write(sockfd, sendline, strlen(sendline));
        if( (= read(sockfd, recvline, MAX_LINE)) == 0)
            exit(0);
        recvline[n]='\0';
        fputs(recvline, stdout);
    }
}
int main(int argc, char **argv)
{
    int sockfd;
    struct sockaddr_in    servaddr;
    
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0)
    {
        printf("create socket error!\n");
        exit(1);
    }
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
    servaddr.sin_port = htons(SERV_PORT);
    connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    str_cli(stdin, sockfd);    
    return 0;
}

源码中需要注意的地方就是tcp服务器代码中的一段:
        if( (childpid = fork()) == 0)/*child process*/
        {
            close(listenfd);
            str_echo(connfd);
            exit(0);
        }
这里在子进程中,首先将listenfd关闭,因为fork函数后,子进程会获得父进程资源的副本,而子进程中并不需要listenfd,直接关闭免的出麻烦。在str_echo调用完成后,并没有使用close(connfd),而是直接调用exit函数。这里我们看下exit函数究竟会做什么。

 

exit调用之后,会调用退出处理函数,这里就是一些对资源的释放,包括已打开的套接字。

直接在linux上编译运行服务器端:


服务端启动后会在5678端口上监听:

然后启动客户端:
并在输入端输入hello,world<回车>后,会显示hello,world,此时我们再看下网络连接状况:
可以看出,服务端在接收到一个连接请求后,fork了一个子进程进行处理,主进程仍然在监听。同时,客户端和服务器端已经建立了连接。
当我们在客户端按下ctrl+d退出之后,再看下网络连接:
服务器的主进程仍然在监听,而客户端的socket套接字的tcp状态处于time_wait状态,至于为什么会到time_wait状态可以看下我以前的博文。此时,服务器的子进程已经退出,我们可以看下进程的状态:
stat中Z表示僵死。可以看出tcp主进程阻塞与accept函数,子进程虽然退出,但是处于僵死状态。这是因为,子进程退出时,会向父进程发送一个SIGCHLD的信号,一般情况下,父进程接收到该信号后,负责对子进程进行清理工作。但是我们在父进程中并没有处理该信号,于是,子进程便处于僵死状态,所占用的资源并没释放。其实,这段代码并未对异常进程处理,所以健壮性方面很差。

分享到:
评论

相关推荐

    TCP/IP通信简单事例

    TCP/IP通信简单事例主要涉及的是网络编程的基本概念和C#及MFC(Microsoft Foundation Classes)的应用。在本文中,我们将深入探讨如何使用C#创建服务端,以及如何利用MFC构建客户端,以便进行结构体的数据传输。 ...

    C#实现 TCP/UDP与串口之间相互转发通信,包含多个实例,有心跳过滤等

    C#实现 TCP/UDP与串口之间相互转发通信,包含多个实例,有心跳过滤等。包含串口之间相互转发。UDP与串口之间转发,TCP与串口之间相互转发。注释比较少,包含各种情况模拟事例,可自行参考相关描述。工程内包含多个...

    QT中tcp数据传输的事例程序

    在QT中,我们可以使用QTcpSocket类来实现TCP通信。首先,我们需要包含必要的头文件,并创建QTcpSocket对象。 ```cpp #include #include QTcpSocket *socket = new QTcpSocket(this); ``` 在TCP通信中,我们通常...

    S7-1200_ModbusTCP_Server.zip_S7-1200_S7-1200_ModbusTCP_s7_1200_西

    《西门子S7-1200 PLC与Modbus TCP通信详解》 在工业自动化领域,西门子S7-1200系列PLC因其高效、灵活和易用性而广受欢迎。同时,Modbus TCP作为一种通用的工业以太网通信协议,也常被用于设备间的通信。本文将深入...

    Modbus事例(net.c#)

    1. **Modbus库选择**:C#中有多个开源库可用于实现Modbus通信,如NModbus,这是一个流行且功能强大的库,支持Modbus RTU和TCP。在案例"Modbus Poll CS"中,可能使用的就是类似这样的库来实现Modbus通信。 2. **连接...

    wcf 服务器 客户端正简单 事例

    在.NET框架中,Windows Communication Foundation(WCF)是一种用于构建分布式应用程序的服务模型,它整合了多种通信技术,如Web服务、消息队列、TCP/IP等。本“WCF服务器和客户端简单事例”旨在帮助初学者理解WCF的...

    vc网络编程事例

    "vc网络编程事例"这个资源很可能是提供了一些实用的示例代码,帮助初学者或者开发者深入理解如何在VC++环境下实现网络通信。 首先,VC++中的网络编程主要依赖于Winsock库,这是一个Windows操作系统提供的接口,用于...

    C#网络编程及应用事例

    《C#网络编程及应用事例》是一份深入探讨C#语言在网络编程领域的实践教程,旨在帮助学习者理解和掌握如何利用C#进行高效且可靠的网络通信。这份讲义结合了理论知识与实际案例,使读者能够更好地将所学应用于实际项目...

    ios socket 文件及 demo事例

    在压缩包中的“demo事例”部分,你可以找到如何使用`CocoaAsyncSocket`的实例代码。通常,这些示例会展示如何创建Socket连接、发送和接收数据,以及如何正确处理连接的建立、断开和错误。通过研究这些示例,你可以...

    udp 小事例

    在这个"udp 小事例"中,我们将探讨如何使用UDP实现一个简单的服务器-客户端通信。 首先,我们来看UDP的特点: 1. **无连接**:UDP不建立连接,因此没有连接建立和释放的过程,减少了开销。 2. **不可靠**:UDP不...

    经典 Socket 多线程事例

    总结一下,这个“经典Socket多线程事例”涵盖了网络编程的核心——Socket通信和多线程技术。通过这个实例,你可以深入理解如何构建一个能同时处理多个客户端连接的服务器,这对于任何希望涉足网络编程的开发者来说都...

    基于C#的socket通信编程

    Socket类是网络通信的核心,它允许程序通过TCP/IP协议发送和接收数据。TCP提供了一种可靠的、面向连接的数据传输服务,适合于文件传输等需要保证数据完整性的场景。 首先,我们要了解Socket的基本工作流程。创建...

    c# IM 类qq即时通讯软件事例

    C#可以使用`System.Net.Sockets`库创建TCP连接,实现客户端与服务器间的可靠数据传输。 3. **聊天室与私聊**:为了支持多对一(群聊)和一对一(私聊)通信,我们需要设计消息路由机制。C#的多线程和异步编程模型能...

    CSocket的一个实例

    在本文中,我们将深入探讨如何使用CSocket进行TCP通信,并通过实例来阐述其工作原理。 TCP(传输控制协议)是一种面向连接的、可靠的网络通信协议,它保证了数据的有序、无损传输。CSocket类提供了与TCP套接字相关...

    事例_多线程 TCIIP 侦听器(VB.NET)

    TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,而IP(互联网协议)则是负责在网络中传输数据包的网络层协议。组合起来,TCP/IP构成了互联网通信的基础。 在VB.NET中实现TCP监听器,...

    delphi socket编程事例

    Delphi Socket编程是一种在Delphi开发环境中实现网络通信的技术,主要涉及到TCP/IP协议栈的使用。Socket编程在软件开发中广泛应用于服务器与客户端之间的数据交换,例如即时通讯、文件传输、远程控制等场景。本节将...

    局域网聊天源代码,一个简单的事例

    - **IP与端口**:局域网聊天应用基于TCP/IP协议栈运行,每个通信节点都有唯一的IP地址和端口号,用于识别和定位网络上的设备。 - **UDP与TCP**:通常,聊天应用可以选择使用UDP(User Datagram Protocol)或TCP...

    c# 精典事例

    在C#中,System.Net命名空间提供了Socket类,用于实现TCP/IP或UDP/IP协议的网络通信。通过创建Socket实例,设置其属性(如IP地址和端口号),并调用Connect或BeginConnect方法连接到远程服务器,然后可以使用Send和...

    一个关于Socket非常好的事例代码

    TCP Socket提供面向连接的服务,即在数据传输前先建立连接,通过三次握手确保双方都可以正常通信。在EasyChat中,可能包含服务器端和客户端两部分代码。服务器端需要监听特定的端口号,等待客户端的连接请求。一旦...

Global site tag (gtag.js) - Google Analytics