4.1 TCP的服务器端/客户端1

来源:互联网 发布:淘宝拍婚纱照靠谱吗 编辑:程序博客网 时间:2024/06/03 14:43

零、 IP地址

IPv4 4字节地址簇

IPv6 16字节地址簇


IPv4标准的4字节IP地址分为网络地址和主机地址,分成A/B/C/D/E等类型。


  A类地址的首字节范围:0-127

  B类地址的首字节范围:128-191

  C类地址的首字节范围:192-223


另一种表达方法:

  A类地址的首位以0开始

  B类地址的前2位以10开始

  C类地址的前3位以110开始


一、 理解下TCP和UDP

根据数据传输方式的不同,基于网络协议的套接字一般分成TCP套接字和UDP套接字。

TCP套接字是面向连接的,又称为基于流Stream的套接字,TCP(Transmission Control Protocol 传输控制协议)的简写,书中将TCP/IP协议栈分成4层架构,掌握这4层协议栈就足够了。另外不同于OSI 7层架构:物理层-->数据链路层-->网络层-->传输层-->会话层-->表示层-->应用层。


1. 链路层:是物理链接领域标准化的结果,也是最基本的领域,专门定义LAN,WAN,MAN等网络标准。

2. IP层:复杂网络中,负责路径的选择。IP本身是面向消息的,不可靠的协议。

3. TCP/UDP层:已IP层提供的路劲信息为基础完成实际的数据传输,因此也称为传输层。TCP比UDP复杂,TCP可以保证可靠的数据传输。

4. 应用层:根据程序特点决定服务器端和客户端之间数据传输规则。


二、 实现基于TCP的服务器端和客户端

1. TCP服务器端的默认函数调用顺序


#include <sys/socket.h>int socket(int domain, int type, int protocol);  成功时返回文件描述符,失败时返回-1.    domain 套接字中使用的协议簇信息;  type 套接字数据传输类型信息;  protocol 计算机间通信使用的协议信息。


#include <sys/socket.h>int bind(int sockfd, struct sockaddr *myaddr, socklen_t addrlen);  成功时返回0,失败时返回-1    sockfd 要分配地址信息的套接字文件描述符  myaddr 存有地址信息的结构体变量地址值  addrlen 第二个结构体变量的长度

#include <sys/socket.h>int listen(int sock, int backlog);  成功时返回0,失败时返回-1    sock 希望进入等待连接请求状态的套接字文件描述符,传递的描述符套接字参数成为服务器端套接字  backlog 连接请求等待队列长度,若为5,则队列长度为5,表示最多5个连接请求进入队列。

#include <sys/socket.h>int accept(int sock, struct sockaddr *addr, socklen_t *addrlen);    成功时返回创建的套接字文件描述符,失败时返回-1  sock 服务器套接字的文件描述符  addr保存发起连接请求的客户端地址信息的变量地址值,函数调用后传递来的地址变量参数填充客户端地址信息  addrlen 第二个参数addr结构体的长度

#include <sys/socket.h>int connect (int sock, struct sockaddr *servaddr, socklen_t addrlen);  成功时返回0,失败时返回-1    sock 客户端套接字文件描述符  servaddr 保存目标服务器端地址信息的变量地址值  addrlen 以字节为单位传递已传递给第二个结构体参数servaddr的地址变量长度


三、迭代回声服务器端、客户端


服务器端在同一时刻只与一个客户端相连,并提供回声服务;

    服务器端依次向5个客户端提供服务并退出

  客户端接收用户输入的字符串并发送给服务器

服务器端将接收到的字符串传回客户端

服务器与客户端之间的字符串回声一直到执行到客户端输入Q为止。


Server代码:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <arpa/inet.h>#include <sys/socket.h>#define BUF_SIZE 1024void error_handling(char *message);int main(int argc, char *argv[]){int serv_sock;int clnt_sock;char message[BUF_SIZE];int str_len,i;struct sockaddr_in serv_addr;struct sockaddr_in clnt_addr;socklen_t clnt_addr_size;if(argc != 2){printf("Usage : %s <port>\n",argv[0]);exit(1);}serv_sock = socket(PF_INET,SOCK_STREAM,0);if(serv_sock == -1){error_handling("socket() error");}memset(&serv_addr,0,sizeof(serv_addr));serv_addr.sin_family=AF_INET;serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);serv_addr.sin_port=htons(atoi(argv[1]));if(bind(serv_sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr)) == -1){error_handling("bind() error");}if(listen(serv_sock,5) == -1){error_handling("listen() error");}clnt_addr_size = sizeof(clnt_addr);for(i=0;i<5;i++){clnt_sock = accept(serv_sock,(struct sockaddr *)&clnt_addr,&clnt_addr_size);if(clnt_sock == -1){error_handling("accept() error");}else{printf("Connected client %d\n",i+1);}while((str_len = read(clnt_sock,message,BUF_SIZE)) != 0){write(clnt_sock,message,str_len);printf("client %d:message %s",i+1,message);}close(clnt_sock);}close(serv_sock);return 0;}void error_handling(char *message){fputs(message,stderr);fputs("\n",stderr);exit(1);}


Client代码:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <arpa/inet.h>#include <sys/socket.h>#define BUF_SIZE1024void error_handling(char *message);int main(int argc,char *argv[]){int sock;struct sockaddr_in serv_addr;char message[BUF_SIZE];int str_len;if(argc != 3){printf("Usage : %s <IP> <port>\n",argv[0]);exit(1);}sock = socket(PF_INET,SOCK_STREAM,0);if(sock == -1){error_handling("socket() error");}memset(&serv_addr,0,sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = inet_addr(argv[1]);serv_addr.sin_port = htons(atoi(argv[2]));if(connect(sock,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) == -1){error_handling("connect() error\r\n");}else{printf("Connected....");}while(1){printf("Input message(Q to quit):");fgets(message,BUF_SIZE,stdin);if(!strcmp(message,"q\n") || !strcmp(message,"Q\n"))break;write(sock,message,strlen(message));str_len = read(sock,message,BUF_SIZE-1);message[str_len] = 0;printf("Message from server : %s \n",message);}close(sock);return 0;}void error_handling(char *message){fputs(message,stderr);fputs("\n",stderr);exit(1);}


执行结果:


alex@alex-VirtualBox:~/Share/Test/tcpip$ ./echo_client 127.0.0.1 9190Connected....Input message(Q to quit):helloMessage from server : helloInput message(Q to quit):whatMessage from server : whatInput message(Q to quit):whoMessage from server : whoInput message(Q to quit):


alex@alex-VirtualBox:~/Share/Test/tcpip$ ./echo_server 9190Connected client 1client 1:message hellolient 1:message whatlient 1:message who



0 0