linux网络编程之socket(七) 一个进程发起多个连接和gethostbyname等函数

一、在前面讲过的最简单的回射客户/服务器程序中,一个客户端即一个进程,只会发起一个连接,只要稍微修改一下就 可以让一个客户端发起多个连接,然后只利用其中一个连接发送数据。

先来认识一个函数getsockname

 #include <sys/socket.h>

 int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

利用此函数可以得到某连接sockfd的地址信息,如ip地址和端口,这可以帮助我们判断发起了多少个连 接。

我们假设一个客户端发起了5个连接,如下图:

此时根据以前说过的fork程序,服务器端会产生5个子进程对其进行服务。

修改过后的客户端程序如下:

/*************************************************************************
    > File Name: echoser.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Fri 01 Mar 2013 06:15:27 PM CST
 ************************************************************************/

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<string.h>
#include "read_write.h"

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

void do_echocli(int sock)
{

    char sendbuf[1024] = {0};
    char recvbuf[1024] = {0};

    while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
    {

        writen(sock, sendbuf, strlen(sendbuf));

        int ret = readline(sock, recvbuf, sizeof(recvbuf)); //按行读取
        if (ret == -1)
            ERR_EXIT("read error");
        else if (ret  == 0)   //服务器关闭
        {
            printf("server close\n");
            break;
        }

        fputs(recvbuf, stdout);

        memset(sendbuf, 0, sizeof(sendbuf));
        memset(recvbuf, 0, sizeof(recvbuf));

    }

    close(sock);
}

int main(void)
{
    int sock[5];
    int i;
    for (i = 0; i < 5; i++)
    {
        if ((sock[i] = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
            //  listenfd = socket(AF_INET, SOCK_STREAM, 0)
            ERR_EXIT("socket error");

        struct sockaddr_in servaddr;
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(5188);
        servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
        /* inet_aton("127.0.0.1", &servaddr.sin_addr); */

        if (connect(sock[i], (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
            ERR_EXIT("connect error");

        struct sockaddr_in localaddr;
        socklen_t addrlen = sizeof(localaddr);
        if (getsockname(sock[i], (struct sockaddr *)&localaddr, &addrlen) < 0)
            ERR_EXIT("getsockname error");
        /* getpeername()获取对等方的地址 */
        printf("local ip=%s port=%d\n", inet_ntoa(localaddr.sin_addr),
               ntohs(localaddr.sin_port));
    }
    /* 一个进程也可以发起多个socket连接,因为每次的端口号都不同 */
    do_echocli(sock[0]); //发起5个套接字连接,但只借助第一个套接口通信

    return 0;
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索include
, sizeof
, gethostbyname
, sock
, 一个
, memset函数
memset()函数
socket.gethostbyname、php 发起socket、socket编程、java socket编程、c socket编程,以便于您获取更多的相关知识。

时间: 2025-01-20 14:04:12

linux网络编程之socket(七) 一个进程发起多个连接和gethostbyname等函数的相关文章

linux网络编程之socket(八) 五种I/O模型和select函数简介

一.五种I/O模型 1.阻塞I/O 我们在前面所说的I/O模型都是阻塞I/O,即调用recv系统调用,如果没有数据则阻塞等待,当数据到来则将数据从内核 空间(套接口缓冲区)拷贝到用户空间(recv函数提供的buf),然后recv返回,进行数据处理. 2.非阻塞 I/O 我们可以使用 fcntl(fd, F_SETFL, flag | O_NONBLOCK); 将套接字标志变成非阻塞,调用recv,如果设备暂时 没有数据可读就返回-1,同时置errno为EWOULDBLOCK(或者EAGAIN,这

linux网络编程之socket(十五) UNIX域套接字编程和socketpair 函数

一.UNIX Domain Socket IPC socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机 制,就是UNIX Domain Socket.虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是 UNIX Domain Socket用于IPC更有效率:不需要经过网络协议栈,不需要打包拆包.计算校验和.维护序号和应答等,只是 将应用层数据从一个进程拷贝到另一个进程.UNIX域套接字与TCP套接字相比较,

linux网络编程之socket(十二) select函数的并发限制和poll函数应用举例

一.用select实现的并发服务器,能达到的并发数,受两方面限制 1.一个进程能打开的最大文件描述符限制. 这可以通过调整内核参数.可以通过ulimit -n来调整或者使用setrlimit函数设置, 但一个系统所能打开的最大数也是有 限的,跟内存大小有关,可以通过cat /proc/sys/fs/file-max 查看 2.select中的fd_set集合容量的限制 (FD_SETSIZE,一般为1024) ,这需要重新编译内核. 可以写个测试程序,只建立连接,看看最多能够建立多少个 连接,客

Linux网络编程之socket文件传输示例_C 语言

本文所述示例程序是基于Linux平台的socket网络编程,实现文件传输功能.该示例是基于TCP流协议实现的socket网络文件传输程序.采用C语言编写.最终能够实现传输任何格式文件的文件传输程序. 具体实现代码如下: Server端代码如下: /************************************************************************* > File Name: Server.c > Author: SongLee ***********

linux网络编程之socket(九) 使用select函数改进客户端/服务器端程序

一.当我们使用单进程单连接且使用readline修改后的客户端程序,去连接使用readline修改后的服务器端程序,会出 现一个有趣的现象,先来看输出: 先运行服务器端,再运行客户端, simba@ubuntu:~/Documents/code/linux_programming/UNP/socket$ ./echoser_recv_peek recv connect ip=127.0.0.1 port=54005 simba@ubuntu:~/Documents/code/linux_prog

linux网络编程之socket(四)

使用fork并发处理多个client的请求和对等通信p2p 一.在前面讲过的回射客户/服务器程序中,服务器只能处理一个客户端的请求,如何同时服务多个客户端呢?在未讲到 select/poll/epoll等高级IO之前,比较老土的办法是使用fork来实现.网络服务器通常用fork来同时服务多个客户端,父 进程专门负责监听端口,每次accept一个新的客户端连接就fork出一个子进程专门服务这个客户端.但是子进程退出时会产 生僵尸进程,父进程要注意处理SIGCHLD信号和调用wait清理僵尸进程,最

linux网络编程之socket(十) shutdown与close函数的区别

假设server和client 已经建立了连接,server调用了close, 发送FIN 段给client(其实不一定会发送FIN段,后面再说 ),此时server不能再通过socket发送和接收数据,此时client调用read,如果接收到FIN 段会返回0,但client此时还是 可以write 给server的,write调用只负责把数据交给TCP发送缓冲区就可以成功返回了,所以不会出错,而server收到数据 后应答一个RST段,表示服务器已经不能接收数据,连接重置,client收到R

linux网络编程之socket(一) socket概述和字节序、地址转换函数

一.什么是socket socket可以看成是用户进程与内核网络协议栈的编程接口. socket不仅可以用于本机的进 程间通信,还可以用于网络上不同主机的进程间通信. socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4.IPv6,以及以后要讲的UNIX Domain Socket.然而,各种网络协议的地址格式并不相同,如下图所示: IPv4和IPv6的地址格式定义在netinet/in.h 中,IPv4地址用sockaddr_in结构体表示,包括16位端口号和32位

linux网络编程之socket(六) 利用recv和readn函数实现readline函数

在前面的文章中,我们为了避免粘包问题,实现了一个readn函数读取固定字节的数据.如果应用层协议的各字段长度固 定,用readn来读是非常方便的.例如设计一种客户端上传文件的协议,规定前12字节表示文件名,超过12字节的文件名截 断,不足12字节的文件名用'\0'补齐,从第13字节开始是文件内容,上传完所有文件内容后关闭连接,服务器可以 先调用readn读12个字节,根据文件名创建文件,然后在一个循环中调用read读文件内容并存盘,循环结束的条件是read返 回0. 字段长度固定的协议往往不够灵