Linux网络编程

本文介绍了三种类型的网络服务器编程实现:TCP服务器、UDP服务器及并发服务器。详细展示了每个服务器的代码实现,包括如何建立连接、接收数据以及处理客户端请求等关键步骤。

1、 tcp程序设计

代码1 server:

[html]  view plain copy
  1. #include <stdlib.h>  
  2. #include <stdio.h>  
  3. #include <errno.h>  
  4. #include <string.h>  
  5. #include <netdb.h>  
  6. #include <sys/types.h>  
  7. #include <netinet/in.h>  
  8. #include <sys/socket.h>  
  9.    
  10. #define portnumber 3333  
  11.    
  12. int main(int argc, char *argv[])  
  13. {  
  14.    int sockfd, new_fd;  
  15.    struct sockaddr_in server_addr;  
  16.    struct sockaddr_in client_addr;  
  17.    int sin_size;  
  18.    int nbytes;  
  19.    char buffer[1024];  
  20.      
  21.    //AF_INET: IPV4, SOCK_STREAM: TCP  
  22.    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)  
  23.     {  
  24.         fprintf(stderr, "Socket error:%s\n\a", strerror(errno));  
  25.        exit(1);  
  26.     }  
  27.    
  28.    bzero(&server_addr, sizeof(struct sockaddr_in));  
  29.    server_addr.sin_family = AF_INET;  
  30.    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);  
  31.    server_addr.sin_port = htons(portnumber);  
  32.    
  33.    if(bind(sockfd, (struct sockaddr *) (&server_addr), sizeof(structsockaddr)) == -1)  
  34.     {  
  35.        fprintf(stderr, "Bind error: %s\n\a", strerror(errno));  
  36.        exit(1);  
  37.     }  
  38.    
  39.    if(listen(sockfd, 5) == -1)  
  40.     {  
  41.        fprintf(stderr, "Listen error: %s\n\a", strerror(errno));  
  42.        exit(1);          
  43.     }  
  44.    
  45.    
  46.    while(1)  
  47.     {  
  48.        sin_size = sizeof(struct sockaddr_in);  
  49.        if((new_fd = accept(sockfd, (struct sockaddr *)(&client_addr),&sin_size)) == -1)  
  50.        {  
  51.             fprintf(stderr, "Accept error:%s\n\a", strerror(errno));  
  52.            exit(1);  
  53.        }  
  54.    
  55.        fprintf(stderr, "Server get connection from %s\n",(char*)inet_ntoa(client_addr.sin_addr));  
  56.    
  57.        if((nbytes = read(new_fd, buffer, 1024)) == -1)  
  58.         {  
  59.            fprintf(stderr, "Read Error: %s\n", strerror(errno));  
  60.            exit(1);  
  61.        }  
  62.    
  63.        buffer[nbytes] = '\0';  
  64.    
  65.        printf("Server received %s\n", buffer);  
  66.    
  67.        close(new_fd);  
  68.     }  
  69.    
  70.    close(sockfd);  
  71.      
  72.    return 0;  
  73. }  


代码2 client:

[html]  view plain copy
  1. #include <stdlib.h>  
  2. #include <stdio.h>  
  3. #include <errno.h>  
  4. #include <string.h>  
  5. #include <netdb.h>  
  6. #include <sys/types.h>  
  7. #include <netinet/in.h>  
  8. #include <sys/socket.h>  
  9.    
  10. #define portnumber 3333  
  11.    
  12. int main(int argc, char *argv[])  
  13. {  
  14.    int sockfd;  
  15.    char buffer[1024];  
  16.    struct sockaddr_in server_addr;  
  17.    struct hostent *host;  
  18.    
  19.    if(argc != 2)  
  20.     {  
  21.        fprintf(stderr, "Usage: %s hostname \a\n", argv[0]);  
  22.        exit(1);  
  23.     }  
  24.    
  25.    if((host = gethostbyname(argv[1])) == NULL)  
  26.     {  
  27.         fprintf(stderr, "Gethostname Error:%s\a\n", strerror(errno));  
  28.        exit(1);  
  29.     }  
  30.    
  31.    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)  
  32.     {  
  33.        fprintf(stderr, "Socket Error: %s\a\n", strerror(errno));  
  34.        exit(1);  
  35.     }  
  36.    
  37.    
  38.    bzero(&server_addr, sizeof(server_addr));  
  39.    server_addr.sin_family = AF_INET;  
  40.    server_addr.sin_port = htons(portnumber);  
  41.    server_addr.sin_addr = *((struct in_addr *) host->h_addr);  
  42.    
  43.    if(connect(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr))== -1)  
  44.     {  
  45.        fprintf(stderr, "Connect Error: %s\a\n", strerror(errno));  
  46.        exit(1);  
  47.     }  
  48.    
  49.    printf("Please input char: \n");  
  50.    
  51.    fgets(buffer, 1024, stdin);  
  52.    write(sockfd, buffer, strlen(buffer));  
  53.    
  54.    close(sockfd);  
  55.    
  56. return 0;  
  57. }  


Makefile:

[html]  view plain copy
  1. CC = gcc  
  2.    
  3. CURTDIR = $(shell pwd)  
  4. TARGET = tcp_client  
  5. #TARGET = tcp_server  
  6.    
  7. %.o:%.c  
  8.        $(CC)-c $(EXTRAFLAGS) $< -o $@  
  9. %.o:%.S  
  10.        $(CC)-c $(EXTRAFLAGS) $< -o $@  
  11.    
  12. .PHONY: all clean  
  13.    
  14. $(TARGET): $(TARGET).o  
  15.        $(CC)  -o $@ $^  
  16.    
  17. clean:  
  18.        rm-rf $(TARGET) $(TARGET).o  


运行结果:

[html]  view plain copy
  1. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.1$make  
  2. gcc -c tcp_server.c -o tcp_server.o  
  3. gcc -o tcp_server tcp_server.o  
  4.    
  5. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.1$ls  
  6. Makefile tcp_client.c  tcp_server  tcp_server.c tcp_server.o  
  7.    
  8. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.1$make  
  9. gcc -c tcp_client.c -o tcp_client.o  
  10. gcc -o tcp_client tcp_client.o  
  11.    
  12. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.1$ls  
  13. Makefile tcp_client  tcp_client.c  tcp_client.o tcp_server  tcp_server.c  tcp_server.o  
  14.    
  15.    
  16. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.1$./tcp_client 192.0.4.87  
  17. Please input char:  
  18. hello mytcp  
  19.    
  20. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.1$./tcp_client 192.0.4.87  
  21. Please input char:  
  22. I am back!  
  23.    
  24. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.1$./tcp_server  
  25. Server get connection from 192.0.4.87  
  26. Server received hello mytcp  
  27.    
  28. Server get connection from 192.0.4.87  
  29. Server received I am back!  


总结:当没有client连接上时,server程序阻塞在accept函数上,等待连接。当有client连接上来时,阻塞在read函数上,等待读取消息。Client发送一条消息后结束,server读出消息打印,继续等待新的连接

 

 

2、 udp程序设计

代码1 server:

[html]  view plain copy
  1. #include <stdlib.h>  
  2. #include <stdio.h>  
  3. #include <errno.h>  
  4. #include <string.h>  
  5. #include <netdb.h>  
  6. #include <sys/types.h>  
  7. #include <netinet/in.h>  
  8. #include <sys/socket.h>  
  9.    
  10. #define portnumber 3333  
  11. #define MAX_MSG_SIZE 1024  
  12.    
  13. void udps_respon(int sockfd)  
  14. {  
  15.    struct sockaddr_in addr;  
  16.    int addrlen, n;  
  17.    char msg[MAX_MSG_SIZE];  
  18.    
  19.    while(1)  
  20.     {  
  21.        bzero(msg, sizeof(msg));  
  22.        addrlen = sizeof(struct sockaddr);  
  23.        n = recvfrom(sockfd, msg, MAX_MSG_SIZE, 0, (struct sockaddr *)&addr,&addrlen);  
  24.        msg[n] = 0;  
  25.        fprintf(stdout, "Server had received %s\n", msg);  
  26.     }  
  27. }  
  28.    
  29. int main(int argc, char *argv[])  
  30. {  
  31.    int sockfd;  
  32.    struct sockaddr_in addr;  
  33.      
  34.    //AF_INET: IPV4, SOCK_DGRAM: UDP  
  35.    if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)  
  36.     {  
  37.        fprintf(stderr, "Socket error: %s\n\a", strerror(errno));  
  38.        exit(1);  
  39.     }  
  40.    
  41.    bzero(&addr, sizeof(struct sockaddr_in));  
  42.     addr.sin_familyAF_INET;  
  43.    addr.sin_addr.s_addr = htonl(INADDR_ANY);  
  44.    addr.sin_port = htons(portnumber);  
  45.    
  46.    if(bind(sockfd, (struct sockaddr *) (&addr), sizeof(structsockaddr)) == -1)  
  47.     {  
  48.        fprintf(stderr, "Bind error: %s\n\a", strerror(errno));  
  49.        exit(1);  
  50.     }  
  51.    
  52.    udps_respon(sockfd);  
  53.    
  54.    close(sockfd);  
  55.         
  56.    return 0;  
  57. }  


代码2 client:

[html]  view plain copy
  1. #include <stdlib.h>  
  2. #include <stdio.h>  
  3. #include <errno.h>  
  4. #include <string.h>  
  5. #include <netdb.h>  
  6. #include <sys/types.h>  
  7. #include <netinet/in.h>  
  8. #include <sys/socket.h>  
  9.    
  10. #define portnumber 3333  
  11. #define MAX_BUF_SIZE 1024  
  12.    
  13. void udpc_requ(int sockfd, const structsockaddr_in *addr, int len)  
  14. {  
  15.    char buffer[MAX_BUF_SIZE];  
  16.    int n;  
  17.    
  18.    while(1)  
  19.     {  
  20.        printf("Please input char: \n");  
  21.         fgets(buffer, MAX_BUF_SIZE, stdin);  
  22.        sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr*)addr, len);  
  23.        bzero(buffer, MAX_BUF_SIZE);  
  24.     }  
  25. }  
  26.    
  27. int main(int argc, char *argv[])  
  28. {  
  29.    int sockfd;  
  30.    struct sockaddr_in addr;  
  31.    
  32.    if(argc != 2)  
  33.     {  
  34.        fprintf(stderr, "Usage: %s hostname \a\n", argv[0]);  
  35.        exit(1);  
  36.     }  
  37.    
  38.    if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)  
  39.     {  
  40.        fprintf(stderr, "Socket Error: %s\a\n", strerror(errno));  
  41.        exit(1);  
  42.     }  
  43.    
  44.     bzero(&addr,sizeof(struct sockaddr_in));  
  45.    addr.sin_family = AF_INET;  
  46.    addr.sin_port = htons(portnumber);  
  47.    if(inet_aton(argv[1], &addr.sin_addr) < 0)  
  48.     {  
  49.        fprintf(stderr, "IP error:%s\n", strerror(errno));  
  50.        exit(1);  
  51.     }  
  52.     
  53.    udpc_requ(sockfd, &addr, sizeof(struct sockaddr_in));  
  54.     
  55.    close(sockfd);  
  56.    
  57. return 0;  
  58. }  


Makefile:

[html]  view plain copy
  1. CC = gcc  
  2.    
  3. CURTDIR = $(shell pwd)  
  4. TARGET = udp_client  
  5. #TARGET = udp_server  
  6.    
  7. %.o:%.c  
  8.        $(CC)-c $(EXTRAFLAGS) $< -o $@  
  9. %.o:%.S  
  10.        $(CC)-c $(EXTRAFLAGS) $< -o $@  
  11.    
  12. .PHONY: all clean  
  13.    
  14. $(TARGET): $(TARGET).o  
  15.        $(CC)  -o $@ $^  
  16.    
  17. clean:  
  18.        rm-rf $(TARGET) $(TARGET).o  
  19.    


运行结果:

[html]  view plain copy
  1. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.2$make  
  2. gcc -c udp_server.c -o udp_server.o  
  3. gcc -o udp_server udp_server.o  
  4.    
  5. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.2$make  
  6. gcc -c udp_client.c -o udp_client.o  
  7. gcc -o udp_client udp_client.o  
  8.    
  9. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.2$./udp_client 192.0.4.87  
  10. Please input char:  
  11. hello myudp               
  12. Please input char:  
  13. good-buy  
  14. Please input char:  
  15.    
  16. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.2$./udp_server  
  17. Server had received hello myudp  
  18.    
  19. Server had received good-buy  
  20.    

总结:当没有client连接上时,server处于阻塞状态,阻塞在recvfrom函数上。当有client连接上来时。Client发送一条消息后结束,server读出消息打印。

 

 

3、 并发服务器设计

代码1 server:

[html]  view plain copy
  1. #include <stdlib.h>  
  2. #include <stdio.h>  
  3. #include <errno.h>  
  4. #include <string.h>  
  5. #include <netdb.h>  
  6. #include <sys/types.h>  
  7. #include <netinet/in.h>  
  8. #include <sys/socket.h>  
  9. #include <pthread.h>  
  10.    
  11. #define portnumber 3333  
  12.    
  13. void *thr_fn(void *arg)  
  14. {  
  15.    int size, j;  
  16.    char recv_buff[1024];  
  17.    int *parg = (int *)arg;  
  18.    int new_fd = *parg;  
  19.      
  20.    printf("new_fd = %d\n", new_fd);  
  21.    
  22.    while((size = read(new_fd, recv_buff, 1024)) > 0)  
  23.     {  
  24.        if(recv_buff[0] == '@')  
  25.            break;  
  26.          
  27.        printf("Message from client(%d): %s\n", size, recv_buff);  
  28.          
  29.        for(j = 0; j < size; j++)  
  30.        {  
  31.            recv_buff[j] = toupper(recv_buff[j]);  
  32.        }  
  33.        write(new_fd, recv_buff, size);  
  34.    
  35.        memset(recv_buff, 0, sizeof(recv_buff));  
  36.     }  
  37.    
  38.    close(new_fd);  
  39.    
  40.    return NULL;  
  41. }  
  42.    
  43. int main(int argc, char *argv[])  
  44. {  
  45.    int listen_sockfd;  
  46.    int com_fd;  
  47.    int i;  
  48.    static char recv_buff[1024];  
  49.    int len;  
  50.    int port;  
  51.    pthread_t tid;  
  52.    socklen_t clt_addr_len;  
  53.    
  54.    struct sockaddr_in server_addr;  
  55.    struct sockaddr_in client_addr;  
  56.     
  57.    if(argc != 2)  
  58.     {  
  59.        printf("Usage: %s port\n", argv[0]);  
  60.        return 1;  
  61.     }  
  62.    
  63.    port = atoi(argv[1]);  
  64.    
  65.    if((listen_sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)  
  66.     {  
  67.        fprintf(stderr, "Socket error: %s\n\a", strerror(errno));  
  68.        exit(1);  
  69.     }  
  70.    
  71.    memset(&server_addr, 0, sizeof(server_addr));  
  72.    server_addr.sin_family = AF_INET;  
  73.    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);  
  74.    server_addr.sin_port = htons(port);  
  75.    
  76.    if(bind(listen_sockfd, (struct sockaddr *) (&server_addr),sizeof(struct sockaddr)) == -1)  
  77.     {  
  78.        fprintf(stderr, "Bind error: %s\n\a", strerror(errno));  
  79.        close(listen_sockfd);  
  80.        exit(1);  
  81.     }  
  82.    
  83.    if(listen(listen_sockfd, 5) == -1)  
  84.     {  
  85.        fprintf(stderr, "Listen error: %s\n\a", strerror(errno));  
  86.        close(listen_sockfd);  
  87.        exit(1);          
  88.     }  
  89.    
  90.    while(1)  
  91.     {  
  92.        len = sizeof(client_addr);  
  93.        com_fd = accept(listen_sockfd, (struct sockaddr*)&client_addr,&len);  
  94.        if(com_fd < 0)  
  95.        {  
  96.            if(errno == EINTR)  
  97.            {  
  98.                 continue;  
  99.            }  
  100.             else  
  101.            {  
  102.                 perror("cannot acceptclient connect request\n");  
  103.                 close(listen_sockfd);  
  104.                 return 1;  
  105.            }  
  106.        }  
  107.        printf("com_fd = %d\n", com_fd);  
  108.    
  109.        if((pthread_create(&tid, NULL, thr_fn, &com_fd)) == -1)  
  110.        {  
  111.            perror("pthread_create error");  
  112.            close(listen_sockfd);  
  113.            close(com_fd);  
  114.            return 1;  
  115.        }  
  116.     }  
  117.    
  118.    return 0;  
  119. }  


代码2 client:

[html]  view plain copy
  1. #include <stdlib.h>  
  2. #include <stdio.h>  
  3. #include <errno.h>  
  4. #include <string.h>  
  5. #include <netdb.h>  
  6. #include <sys/types.h>  
  7. #include <netinet/in.h>  
  8. #include <sys/socket.h>  
  9. #include <unistd.h>  
  10. #include <sys/un.h>  
  11.    
  12. #define portnumber 3333  
  13.    
  14. int main(int argc, char *argv[])  
  15. {  
  16.    int connect_fd;  
  17.    int ret;  
  18.    char snd_buf[1024];  
  19.    int i;  
  20.    int port;  
  21.    int len;  
  22.    static struct sockaddr_in server_addr;  
  23.    
  24.    if(argc != 3)  
  25.     {  
  26.        fprintf(stderr, "Usage: %s ip \a\n", argv[0]);  
  27.        exit(1);  
  28.     }  
  29.    
  30.    port = atoi(argv[2]);  
  31.    
  32.    if((connect_fd = socket(PF_INET, SOCK_STREAM, 0)) == -1)  
  33.     {  
  34.        fprintf(stderr, "Socket Error: %s\a\n", strerror(errno));  
  35.        exit(1);  
  36.     }  
  37.    
  38.    bzero(&server_addr, sizeof(server_addr));  
  39.    server_addr.sin_family = AF_INET;  
  40.    server_addr.sin_addr.s_addr = inet_addr(argv[1]);  
  41.    server_addr.sin_port = htons(port);  
  42.    
  43.    if(connect(connect_fd, (struct sockaddr *)(&server_addr),sizeof(struct sockaddr)) == -1)  
  44.     {  
  45.        fprintf(stderr, "Connect Error: %s\a\n", strerror(errno));  
  46.        exit(1);  
  47.     }  
  48.    
  49.    memset(snd_buf, 0, 1024);  
  50.      
  51.    while(1)  
  52.     {  
  53.        printf("input message: \n");  
  54.    
  55.        memset(snd_buf, 0, sizeof(snd_buf));         
  56.        fgets(snd_buf, 1024, stdin);  
  57.            
  58.        len = strlen(snd_buf);  
  59.    
  60.        write(connect_fd, snd_buf, len);  
  61.         
  62.        len = read(connect_fd, snd_buf, len);  
  63.        if(len > 0)  
  64.            printf("Message from server: %s\n", snd_buf);  
  65.        if(snd_buf[0] == '@')  
  66.            break;  
  67.     }  
  68.      
  69.    close(connect_fd);  
  70.    
  71. return 0;  
  72. }  

 

Makefile:

[html]  view plain copy
  1. CC = gcc  
  2.    
  3. CURTDIR = $(shell pwd)  
  4. #TARGET = thread_client  
  5. TARGET = thread_server  
  6.    
  7. %.o:%.c  
  8.        $(CC)-c $(EXTRAFLAGS) $< -o $@  
  9. %.o:%.S  
  10.        $(CC)-c $(EXTRAFLAGS) $< -o $@  
  11.    
  12. .PHONY: all clean  
  13.    
  14. $(TARGET): $(TARGET).o  
  15.        $(CC)  -o $@ $^ -lpthread  
  16.    
  17. clean:  
  18.        rm-rf $(TARGET) $(TARGET).o  
  19.    

 

运行结果:

[html]  view plain copy
  1. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.3$make  
  2. gcc -c thread_server.c -o thread_server.o  
  3. gcc -o thread_server thread_server.o -lpthread  
  4.    
  5. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.3$ls  
  6. Makefile thread_client.c thread_server thread_server.c  thread_server.o  
  7.    
  8.    
  9. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.3$make  
  10. gcc -c thread_client.c -o thread_client.o  
  11. gcc -o thread_client thread_client.o -lpthread  
  12.    
  13. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.3$ls  
  14. Makefile thread_client thread_client.c thread_client.o  thread_server  thread_server.c  thread_server.o  
  15.    
  16.    
  17. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.3$./thread_client 192.0.4.87 2222  
  18. input message:  
  19. hello, i am the 1st  
  20. Message from server: HELLO, I AM THE 1ST  
  21.    
  22. input message:  
  23. @  
  24. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.3$./thread_client 192.0.4.87 2222  
  25. input message:  
  26. hello, i am the 1st, i am back  
  27. Message from server: HELLO, I AM THE 1ST, IAM BACK  
  28.    
  29. input message:  
  30. @  
  31.    
  32.    
  33. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.3$./thread_client 192.0.4.87 2222  
  34. input message:  
  35. hi, i am the 2nd  
  36. Message from server: HI, I AM THE 2ND  
  37.    
  38. input message:  
  39. @    
  40.    
  41.    
  42. eastmoon@eastmoon-virtual-machine:~/work/guoqian/4/4.3$./thread_server 2222  
  43. com_fd = 4  
  44. new_fd = 4  
  45. Message from client(20): hello, i am the1st  
  46.    
  47. com_fd = 5  
  48. new_fd = 5  
  49. Message from client(17): hi, i am the 2nd  
  50.    
  51. com_fd = 6  
  52. new_fd = 6  
  53. Message from client(31): hello, i am the1st, i am back  
  54.    


       总结:并发服务器由于使用了多线程或者多进程,所以能同事接受多个客户端的连接。循环服务器只有在一个连接断掉之后才能接受另一个连接,因为服务器进程正在执行对客户端的消息收发不能继续循环去接受新的连接。


原文:http://blog.youkuaiyun.com/eastmoon502136/article/details/8567075

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值