织梦CMS - 轻松建站从此开始!

罗索

Linux下各类TCP网络服务器的实现源代码

jackyhwei 发布于 2011-06-16 21:46 点击:次 
大家都知道各类网络服务器程序的编写步骤,并且都知道网络服务器就两大类:循环服务和并发服务。这里附上源代码来个小结吧。
TAG:

http://blog.csdn.net/hwz119/archive/2007/05/23/1621887.aspx

大家都知道各类网络服务器程序的编写步骤,并且都知道网络服务器就两大类:循环服务和并发服务。这里附上源代码来个小结吧。

首先,循环网络服务器编程实现的步骤是这样的:

                              建立socket(这里用到socket()函数及函数setsockopt())
                                                            |
                                                            |
                                                           \|/
                              把socket和IP地址及端口绑定(这里用到bind函数)
                                                            |
                                                            |
                                                           \|/
                              开始监听(这里用到listen()函数)
                                                            |
                                                            |
                                                           /\
                                                       /        \
                                               \     /           \
                    -----------------------  | 有连接|
                    |                           /   \             /
                    |                                 \         /
                    |                                     \ /
                    |                                       |
                    |          接受新的连接(这里用到accept()函数)
                    |                                       |  /___________________________________________________
                    |                                       |  \                                                                                                      |
                    |                                     \|/                                                                                                         |
                    |         从连接里读取数据(这里用到recv()系统函数,当然也可以是read()函数)                      |
                    |                                        |                                                                                                        |
                    |                                       |                                                                                                         |
                    |                                     \|/                                                                                                         |
                    |          返回信息给连接(这里用到send()系统函数,当然也可以是write()函        数)                |
                    |                                       |                                                                                                         |
                    |                                       |                                                                                                         |
                    |                                      /\                                                                                                         |
                    |                                  /        \                                                                                                     |
                    |                               /               \                                                                                                 |
                    |                              | 还有数据 |-Y-------------------------------------------------------
                    |                              \               /
                    |                                 \         /
                    |                                     \ /
                    |________________|

这种服务器模型是典型循环服务,如果不加上多进程/线程技术,此种服务吞吐量有限,大家都可以看到,如果前一个连接服务数据没有收发完毕后面的连接没办法处理。所以一般有多进程技术,对一个新连接启用一个新进程去处理,而监听socket继续监听。

一个循环TCP服务源代码(因为用fork进行多进程服务了,所以这种服务现实中也有用)如下:


/*----------------------源代码开始--------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
int main(int argc, char ** argv)
{
    int sockfd,new_fd; /* 监听socket: sock_fd,数据传输socket: new_fd */
    struct sockaddr_in my_addr; /* 本机地址信息 */
    struct sockaddr_in their_addr; /* 客户地址信息 */
    unsigned int sin_size, myport, lisnum;

    if(argv[1])  myport = atoi(argv[1]);
    else myport = 7838;

    if(argv[2])  lisnum = atoi(argv[2]);
    else lisnum = 2;

    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }
    my_addr.sin_family=PF_INET;
    my_addr.sin_port=htons(myport);
    my_addr.sin_addr.s_addr = INADDR_ANY;
    bzero(&(my_addr.sin_zero), 0);
    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
        perror("bind");
        exit(1);
    }

    if (listen(sockfd, lisnum) == -1) {
        perror("listen");
        exit(1);
    }
    while(1) {
        sin_size = sizeof(struct sockaddr_in);
        if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
            perror("accept");
            continue;
        }
        printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));
        if (!fork()) { /* 子进程代码段 */
            if (send(new_fd, "Hello, world!\n", 14, 0) == -1) {
                perror("send");
                close(new_fd);
                exit(0);
            }
        }
        close(new_fd); /*父进程不再需要该socket*/
        waitpid(-1,NULL,WNOHANG);/*等待子进程结束,清除子进程所占用资源*/
    }
}
/*----------------------源代码结束--------------------------------------------*/


一个测试客户端代码如下:
/*----------------------源代码开始--------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define MAXDATASIZE 100 /*每次最大数据传输量 */
int main(int argc, char *argv[])
{
    int sockfd, numbytes;
    char buf[MAXDATASIZE];
    struct hostent *he;
    struct sockaddr_in their_addr;
    unsigned int myport;

    if(argv[2]) myport = atoi(argv[2]);
    else myport = 7838;

    if (argc != 3) {
        fprintf(stderr,"usage: %s hostname port\n", argv[0]);
        exit(1);
    }
    if((he=gethostbyname(argv[1]))==NULL) {
        herror("gethostbyname");
        exit(1); (zhoulifa)

本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201106/14572.html]
本文出处:zhoulifa.bokee.com 作者:zhoulifa
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容