代码改变世界

Linux网络编程之Helloworld实例

2012-11-02 16:27  Chung-shu  阅读(408)  评论(0)    收藏  举报

1. 服务端程序(server.c)

#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>
#include <memory.h>

/*能够同时接受的连接数*/
#define BACKLOG 10

int main(int argc, char *argv[])
{
    int sockfd, new_fd;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int sin_size, portnumber;
    char hello[]="Hello! Are you OK?\n";
    
    if(argc!=2)
    {
        printf("portnumber error!\n");
        exit(1);
    }
    if((portnumber=atoi(argv[1]))<0)
    {
        printf("portnumber error!\n");
        exit(1);
    }

    /*服务器端建立socket描述符*/
    if((sockfd=socket(AF_INET, SOCK_STREAM, 0))==-1)
    {
        printf("socket error: %s.\n", strerror(errno));
        exit(1);
    } 
    
    /*服务器端填充sockaddr结构*/
    //bzero(&server_addr, sizeof(struct sockaddr_in));
    memset(&server_addr, 0, sizeof(struct sockaddr_in));
    server_addr.sin_family=AF_INET;
    server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    server_addr.sin_port=htons(portnumber);

    /*捆绑sockfd描述符*/
    if(bind(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr))==-1)
    {
        printf("bind error: %s.\n", strerror(errno));
        exit(1);
    }
    
    /*监听sockfd描述符*/
    if(listen(sockfd, BACKLOG)==-1)
    {
        printf("listen error: %s.\n", strerror(errno));
        exit(1);
    }

    while(1)
    {
        /*服务器阻塞,直到客户程序建立连接*/
        sin_size=sizeof(struct sockaddr_in);
        if((new_fd=accept(sockfd, (struct sockaddr *)(&client_addr), &sin_size))==-1)
        {
            printf("accept error: %s.\n", strerror(errno));
            continue;
        }
        
        printf("server get connection from %s\n", inet_ntoa(client_addr.sin_addr));
        
        if(write(new_fd, hello, strlen(hello))==-1)
        {
            printf("write error: %s.\n", strerror(errno));
            exit(1);
        }
        close(new_fd);
    }

    close(sockfd);

    return 0;
}

2. 客户端程序(client.c)

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

int main(int argc, char *argv[])
{
    int sockfd;
    char buffer[1024];
    struct sockaddr_in server_addr;
    unsigned long s_addr;
    int portnumber, nbytes;
    
    if(argc!=3)
    {
        printf("ip address or portnumber error.\n");
        exit(1);
    }
    if((s_addr=inet_addr(argv[1]))==-1)
    {
        printf("ip address or portnumber error.\n");
        exit(1);
    }
    if((portnumber=atoi(argv[2]))<0)
    {
        printf("ip address or portnumber error.\n");
        exit(1);
    }

    /*客户程序开始建立sockfd描述符*/
    if((sockfd=socket(AF_INET, SOCK_STREAM, 0))==-1)
    {
        printf("socket error: %s.\n", strerror(errno));
        exit(1);
    }
    /*客户程序填充服务端信息*/
    //bzero(&server_addr, sizeof(server_addr));
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family=AF_INET;
    server_addr.sin_port=htons(portnumber);
    /*server_addr.sin_addr=*((struct in_addr *)host->h_addr);*/
    server_addr.sin_addr.s_addr=s_addr;

    /*客户端程序发起连接请求*/
    if(connect(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr))==-1)
    {
        printf("connect error: %s.\n", strerror(errno));
        exit(1);
    }
    
    /*连接成功*/
    if((nbytes=read(sockfd, buffer, 1024))==-1)
    {
        printf("read error: %s.\n", strerror(errno));
        exit(1);
    }
    buffer[nbytes]='\0';
    printf("I have received: %s\n", buffer);

    /*结束通信*/
    close(sockfd);
    return 0;
}

3. 由于目标文件需要运行在mips-linux平台下,需要编写Makefile文件

CC=mips-linux-gcc
CFLAGS=-O2 -static
LDFLAGS=-Wl,--trace,--print-map,--cref

all:server client

server:server.o
    $(CC) $(LDFLAGS) -o server server.o

server.o:server.c
    $(CC) -c $(CFLAGS) server.c

client:client.o
    $(CC) $(LDFLAGS) -o client client.o

client.o:client.c
    $(CC) -c $(CFLAGS) client.c

clean:
    rm -f *.o

4. make

将目标文件下载到设备中即可运行。

5. 以上服务器端采用的是循环方式,如果该进程阻塞,则不能响应其他客户端的请求,改为并发方式可以解决这个问题,代码如下:

#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>
#include <memory.h>

/*能够同时接受的连接数*/
#define BACKLOG 10

int main(int argc, char *argv[])
{
    int sockfd, new_fd;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int n, sin_size, portnumber, child_process;
    
    if(argc!=2)
    {
        printf("portnumber error!\n");
        exit(1);
    }
    if((portnumber=atoi(argv[1]))<0)
    {
        printf("portnumber error!\n");
        exit(1);
    }

    /*服务器端建立socket描述符*/
    if((sockfd=socket(AF_INET, SOCK_STREAM, 0))==-1)
    {
        printf("socket error: %s.\n", strerror(errno));
        exit(1);
    } 
    
    /*服务器端填充sockaddr结构*/
    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family=AF_INET;
    server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    server_addr.sin_port=htons(portnumber);

    /*如果服务器终止,可以快速启动而不用等待一段时间*/
    n=1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(int));

    /*捆绑sockfd描述符*/
    if(bind(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr))==-1)
    {
        printf("bind error: %s.\n", strerror(errno));
        exit(1);
    }
    
    /*监听sockfd描述符*/
    if(listen(sockfd, BACKLOG)==-1)
    {
        printf("listen error: %s.\n", strerror(errno));
        exit(1);
    }

    while(1)
    {
        if((new_fd=accept(sockfd, (struct sockaddr *)(&client_addr), &sin_size))==-1)
        {
            printf("accept error: %s.\n", strerror(errno));
            continue;
        }
        if((child_process=fork())==0)
        {
            char hello[30];
            sprintf(hello, "Child Process %d: Hello! Are you OK?", getpid());

            printf("server get connection from %s\n", inet_ntoa(client_addr.sin_addr));
            
            if(write(new_fd, hello, strlen(hello))==-1)
            {
                printf("write error: %s.\n", strerror(errno));
            }
            close(new_fd);
            exit(1);
        }
        else if(child_process==-1)
            printf("fork error: %s.\n", strerror(errno));

        close(new_fd);
    }

    return 0;
}