《UNIX网络编程》之多客户连接服务端,可重用套接字对

该网络编程之客户端与服务端程序模板支持:

1. 多客户端同时连接服务端,即服务程序可以同时为多个客户端服务;

2. 服务端支持套接字对重用,即即使处于TIME_WAIT状态,仍可支持服务端重启;

3. 服务端可以发现客户端是否已断开连接;

4. 支持客户端标准输入会显,服务端从标准输出显示客户端所输入内容。

程序如下,记下该模板以备再次使用:

客户端程序如下:

/*************************************************************************
    > File Name: p2pcli.c
    > Author: ma6174
    > Mail: [email protected]
    > Created Time: Sun 05 Oct 2014 09:26:40 PM HKT
 ************************************************************************/

#include<stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define ERR_EXIT(m)         do         {             perror(m);             exit(EXIT_FAILURE);         }while(0)

int main(int argc, char **argv)
{
    int sockfd;
    struct sockaddr_in servaddr;

    if(argc != 2)
    {
        //printf("usage: p2pcli <IPaddress> ");
        //exit(0);
        ERR_EXIT("usage: p2pcli <IPaddress> ");
    }

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(5188);
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);

    if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
    {
        ERR_EXIT("connect");
    }

    //communication
    char sendbuf[1024] = {0};
    char recvbuf[1024] = {0};
    while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
    {
        //send to server.
        write(sockfd, sendbuf, strlen(sendbuf));
        //read from server to display.
        read(sockfd, recvbuf, sizeof(recvbuf));

        //display
        fputs(recvbuf, stdout);
        memset(sendbuf, 0, sizeof(sendbuf));
        memset(recvbuf, 0, sizeof(recvbuf));
    }
    close(sockfd);
    return 0;
}

服务端程序如下:

/*************************************************************************
    > File Name: p2psrv.c
    > Author: ma6174
    > Mail: [email protected]
    > Created Time: Sun 05 Oct 2014 08:27:06 PM HKT
 ************************************************************************/

#include<stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>

#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>

#define ERR_EXIT(m)        do        {            perror(m);            exit(EXIT_FAILURE);        }while(0)

void do_service(int connfd)
{
    //communication
    char recvbuf[1024];
    while(1)
    {
        memset(recvbuf, 0, sizeof(recvbuf));
        int ret = read(connfd, recvbuf, sizeof(recvbuf));
        if(ret == 0)
        {
            printf("client close.\n");
            break;
        }
        else if(ret == -1)
        {
            break;
        }
        else
        {
            fputs(recvbuf, stdout);
            write(connfd, recvbuf, ret);
        }
    }
}

int main()
{
    int listenfd;
    if( (listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
    {
        ERR_EXIT("socket");
    }

    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(5188);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    //reuse address
    int on = 1;
    if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
    {
        ERR_EXIT("setsockopt");
    }

    if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
    {
        ERR_EXIT("bind");
    }

    if(listen(listenfd, SOMAXCONN) < 0)
    {
        ERR_EXIT("listen");
    }

    struct sockaddr_in peeraddr;
    socklen_t peerlen = sizeof(peeraddr);
    int connfd;

    //muti client
    pid_t pid;
    while(1)
    {
        if( (connfd = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < 0 )
        {
            ERR_EXIT("accept");
        }

        printf("ip=%s, port=%d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));

        pid = fork();
        if(pid == -1)
        {
            ERR_EXIT("fork");
        }
        else if(pid == 0)
        {
            //child
            close(listenfd);
            do_service(connfd);
            exit(0);
        }
        else
        {
            close(connfd);

        }
    }
    close(connfd);
    close(listenfd);
    return 0;
}
时间: 2024-10-14 15:04:26

《UNIX网络编程》之多客户连接服务端,可重用套接字对的相关文章

Unix网络编程学习笔记之第8章 基于UDP套接字编程

一. UDP C/S的典型函数调用 UDP没有像TCP那样的连接,客户端直接sendto向某服务器发送数据,服务器端一直recvfrom阻塞,以接收任何客户端发送的数据. 二. sendto和recvfrom函数 int sendto(int sockfd, const void* buff, size_t nbytes, int flag, const struct sockaddr* to, socklen_taddrlen); int recvfrom(int sockfd, void*

Unix网络编程学习笔记之第4章 基于TCP套接字编程

1. socket函数 int socket(int family, int type,int protocol) 成返回一个套接字描述符.错误返回-1 其中family指定协议族,一般IPv4为AF_INET, IPv6为AF_INET6. 其中type指定套接字类型,字节流:SOCK_STREAM.   数据报:SOCK_DGRAM. 一般情况下通过family和type的组合都可以唯一确定一个套接字类型.所以一般我们就把protocol设为0就可以了. 有时在某些特殊情况下,family和

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

回声客户端问题 上一章TCP/IP网络编程之基于TCP的服务端/客户端(一)中,我们解释了回声客户端所存在的问题,那么单单是客户端的问题,服务端没有任何问题?是的,服务端没有问题,现在先让我们回顾下服务端的I/O代码 echo_server.c --while ((str_len = read(clnt_sock, messag, 1024)) != 0) write(clnt_sock, messag, str_len);-- 接着,我们回顾客户端的代码 echo_client.c -- wr

UNIX网络编程入门——TCP客户/服务器程序详解

前言 最近刚开始看APUE和UNP来学习socket套接字编程,因为网络这方面我还没接触过,要等到下学期才上计算机网络这门课,所以我就找了本教材啃了一两天,也算是入了个门. 至于APUE和UNP这两本书,书是好书,网上也说这书是给进入unix网络编程领域初学者的圣经,这个不可置否,但这个初学者,我认为指的是接受过完整计算机本科教育的研究生初学者,需要具有完整计算机系统,体系结构,网络基础知识.基础没打好就上来啃书反而会适得其反,不过对于我来说也没什么关系,因为基础课也都上得差不多了,而且如果书读

unix网络编程各种TCP客户-服务器程序设计实例附环境搭建和编译方法(一)

一,到http://download.csdn.net/detail/ts173383201/4505201去下载源代码,然后解压: 二,cd到你解压后的文件夹下,就是有configure的那个目录下,执行命令./configure: 三,执行cd lib跳到lib目录下,执行make命令,会在上层目录(就是刚才有configure那个目录)生成libunp.a文件 四,复制这个静态库libunp.a到/usr/lib/和/usr/lib64/中; 五,接下来在目录中找到unp.h和config

【UNIX网络编程】TCP客户/服务器程序示例

做一个简单的回射服务器: 客户从标准输入读入一行文本,写给服务器 -> 服务器从网络输入读入这行文本,并回射给客户 -> 客户从网络输入读入这行回射文本,并显示在标准输出上 以下是我的代码(部分.h文件是由unpv13e文件夹中的.c文件改名得到) #include "../unpv13e/unp.h" #include "../unpv13e/apueerror.h" #include "../unpv13e/wrapsock.h"

Qt学习心得之网络编程简单的局域网聊天服务端建立

学而不思则罔,思而不学则殆.学习和思考是相辅相成的,通过这几天对网络编程的学习,收获颇丰.接下来我将利用Qt做的一个以TcpIp协议为传输方式的简单的局域网聊天服务端与大家分享下: 首先谈谈我个人对Tcp协议的理解:Tcp就是网上购物,买家和买家之间的物品传递,快递公司的扮演.快递公司将卖家所要寄出的物品进行包装,给予独特的号码,并从卖家获取目的地地址,得知这些明确信息后准确将物品送到买家,买家签收后,卖家通过快递单号查询到买家签收的消息. 其次是这个简单局域网聊天服务器的创建思路.如下图是思路

java网络编程TCP传输—流操作—服务端反馈与客户端接收

在读取完流后,服务端会向客户端返回一些数据,告诉客户端,已经写完了. 在这里和”流操作—拿到源后的写入动作“差不多,客户端同样以byte与Buffered两种缓冲读取作为例子,同时,.也是希望大家给补充. 1.利用OutputStream向客户端回写,客户端用byte作为缓冲接收 向客户端回写: 1 //获取socket输出流,将上传成功字样传给客户端 2 OutputStream out=s.getOutputStream(); 3 out.write("上传成功".getBytes

Python网络编程(二)通过ThreadingMixIn实现多线程异步套接字程序

使用ThreadingMixIn类的特点: 在线程间共享应用的状态,与使用ForkingMixIn类相比避免进程间通信的复杂操作. 代码如下: 1 #! /usr/bin/python 2 3 import os 4 import socket 5 import threading 6 import SocketServer 7 8 SERVER_HOST = 'localhost' 9 SERVER_PORT = 0 10 BUF_SIZE = 1024 11 12 def client(ip