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

时间:2022-12-13 17:43:06

零、 IP地址

IPv4 4字节地址簇

IPv6 16字节地址簇


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

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

  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层架构:物理层-->数据链路层-->网络层-->传输层-->会话层-->表示层-->应用层。

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

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

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

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

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


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

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

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

#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的地址变量长度

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

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


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

    服务器端依次向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 1024
void 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_SIZE1024
void 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 9190
Connected....Input message(Q to quit):hello
Message from server : hello

Input message(Q to quit):what
Message from server : what

Input message(Q to quit):who
Message from server : who

Input message(Q to quit):


alex@alex-VirtualBox:~/Share/Test/tcpip$ ./echo_server 9190
Connected client 1
client 1:message hello
lient 1:message what
lient 1:message who