Ch13 TCP/IP和网络编程

Ch13 TCP/IP和网络编程

13.2 TCP/IP

TCP/IP数据流路径

image

13.3 IP主机和IP地址

  • 主机是支持TCP/IP协议的计算机或设备。

  • IP地址分为两部分,即NetworkID字段和HostID字段。

13.4 IP协议

  • IP协议用于在IP主机之间发送/接收数据包,IP协议尽最大努力交付数据包。

13.5 IP数据包格式

IP数据包由IP头、发送方IP地址和接收方IP地址以及数据组成。每个IP数据包的大小最大为64KB。

13.12 网络编程

13.12.2 服务器-客户机计算模型

大多数网络编程任务都基于服务器-客户机计算模型。在服务器-客户机计算模财中我们首先在服务器主机上运行服务器进程。然后,我们从客户机主机运行客户机在UDP中,服务器等待来自客户机的数据报,处理数据报并生成对客户机的响应。在TCP中,服务器等待客户机连接。客户机首先连接到服务器,在客户机和服务器之间建立一个虚拟电路,建立连接后,服务器和客户机可以交换连续的数据流。


13.13 套接字编程

在网络编程中,TCP/IP的用户界面是通过一系列C语言库函数和系统调用来实现的, 这些函数和系统调用统称为套接字API (( Rago 1993; Stevens等2004 )。

13.13.1 套接字地址

struct sockaddr_in {
sa_family_t sin_family; // AF_INET for TCP/IP
in_port_t sin_port; // port number
struct in_addr sin_addr; // IP address
};
struct in_addr { // internet address
uint32_t s_addr; // IP address in network byte order
};
  • TCP/IP 网络的 sin_family 始终设置为 AF_INET。
  • sm_port包含按网络字节顺序排列的端口号。
  • sin_addr是按网络字节顺序排列的主机IP地址。

13.13.2 套接字API

  1. init套接字

    //udp
    int udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
    //tcp
    int tcp_sock = socket(AF_INET, SOCK_STRAM, 0);
    
  2. int bind(int sockfd, struct sockaddr *addr, socklen_t addrlen)

  3. UDP套接字

    ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
    ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
    
  4. TCP套接字

    int listen(int sockfd, int backlog);
    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    
    
  5. send()/read() and recv/write()

    ssize_t send(int sockfd, const void *buf, size_t len, int flags);
    ssize_t write(sockfd, void *buf, size_t, len)
    ssize_t recv(int sockfd, void *buf, size_t len, int flags);
    ssize_t read(sockfd, void *buf, size_t len);
    

------------恢复内容开始------------

# Ch13 TCP/IP和网络编程

13.2 TCP/IP

TCP/IP数据流路径

image

13.3 IP主机和IP地址

  • 主机是支持TCP/IP协议的计算机或设备。

  • IP地址分为两部分,即NetworkID字段和HostID字段。

13.4 IP协议

  • IP协议用于在IP主机之间发送/接收数据包,IP协议尽最大努力交付数据包。

13.5 IP数据包格式

IP数据包由IP头、发送方IP地址和接收方IP地址以及数据组成。每个IP数据包的大小最大为64KB。

13.12 网络编程

13.12.2 服务器-客户机计算模型

大多数网络编程任务都基于服务器-客户机计算模型。在服务器-客户机计算模财中我们首先在服务器主机上运行服务器进程。然后,我们从客户机主机运行客户机在UDP中,服务器等待来自客户机的数据报,处理数据报并生成对客户机的响应。在TCP中,服务器等待客户机连接。客户机首先连接到服务器,在客户机和服务器之间建立一个虚拟电路,建立连接后,服务器和客户机可以交换连续的数据流。


13.13 套接字编程

在网络编程中,TCP/IP的用户界面是通过一系列C语言库函数和系统调用来实现的, 这些函数和系统调用统称为套接字API (( Rago 1993; Stevens等2004 )。

13.13.1 套接字地址

struct sockaddr_in {
sa_family_t sin_family; // AF_INET for TCP/IP
in_port_t sin_port; // port number
struct in_addr sin_addr; // IP address
};
struct in_addr { // internet address
uint32_t s_addr; // IP address in network byte order
};
  • TCP/IP 网络的 sin_family 始终设置为 AF_INET。
  • sm_port包含按网络字节顺序排列的端口号。
  • sin_addr是按网络字节顺序排列的主机IP地址。

13.13.2 套接字API

  1. init套接字

    //udp
    int udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
    //tcp
    int tcp_sock = socket(AF_INET, SOCK_STRAM, 0);
    
  2. int bind(int sockfd, struct sockaddr *addr, socklen_t addrlen)

  3. UDP套接字

    ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
    ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
    
  4. TCP套接字

    int listen(int sockfd, int backlog);
    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    
    
  5. send()/read() and recv/write()

    ssize_t send(int sockfd, const void *buf, size_t len, int flags);
    ssize_t write(sockfd, void *buf, size_t, len)
    ssize_t recv(int sockfd, void *buf, size_t len, int flags);
    ssize_t read(sockfd, void *buf, size_t len);
    

代码实践

参考书上的代码编写了UDP的server端和client端。

UDP

  • server端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#define BUFLEN 256
#define PORT 1234

char line[BUFLEN];
struct sockaddr_in me, client;
int sock, rlen, clen = sizeof(client);

int main(){
	printf("1. create a UDP socket\n");
	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	
	printf("2. file me with server address and port number\n");
	memset((char *)&me, 0, sizeof(me));	
	me.sin_family = AF_INET;
	me.sin_port = htons(PORT);
	me.sin_addr.s_addr = htonl(INADDR_ANY);

	printf("3. bind socket to server IP and port\n");
	bind(sock, (struct sockaddr*)&me, sizeof(me));

	printf("4. wait for datagram\n");
	while(1){
	memset(line, 0, BUFLEN);
	printf("UDP server: waiting for datagram\n");
	
	rlen = recvfrom(sock, line, BUFLEN, 0, (struct sockaddr *)&client, &clen);
	printf("recevied a datagram from [host:port] = [%s:%d]\n",
		inet_ntoa(client.sin_addr), ntohs(client.sin_port));
	printf("rlen=%d: line=%s\n", rlen, line);
	printf("send reply\n");
	sendto(sock, line, rlen, 0, (struct sockaddr*)&client, clen);
}
	return 0;
}
  • client端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>


#define SERVER_HOST "127.0.0.1"
#define SERVER_PORT 1234
#define BUFLEN 256

char line[BUFLEN];
struct sockaddr_in server;
int sock, rlen, slen=sizeof(server);

int main(){
	printf("1. create a UDP socket\n");
	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	
	printf("2. fill in server address and port number\n");
	memset((char *) &server, 0, sizeof(server));
	server.sin_family = AF_INET;
	server.sin_port = htons(SERVER_PORT);
	inet_aton(SERVER_HOST, &server.sin_addr);

	while(1){
	printf("Enter a line :" );
	fgets(line, BUFLEN, stdin);
	line[strlen(line)-1] = 0;
	printf("send line to server\n");
	sendto(sock, line, strlen(line), 0, (struct sockaddr *)&server, slen);
	memset(line, 0, BUFLEN);
	printf("try to receive a line from server\n");
	rlen = recvfrom(sock, line, BUFLEN, 0, (struct sockaddr *)&server, &slen);
	printf("rlen=%d : line=%s\n", rlen, line);
}
	return 0;
}
  • 运行结果
    image
    image

TCP

  • sever端代码
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>

#define MAX 256
#define SERVER_HOST "localhost"
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 1234

struct sockaddr_in server_addr, client_addr;
int mysock, csock; // socket descriptors
int r, len, n;     // help variables

int server_init()
{
    printf("================== server init ======================\n");

    // create a TCP socket by socket() syscall
    printf("1 : create a TCP STREAM socket\n");
    mysock = socket(AF_INET, SOCK_STREAM, 0);

    if (mysock < 0)
    {
        printf("socket call failed\n");
        exit(1);
    }
    printf("2 : fill server_addr with host IP and PORT# info\n");
    // initialize the server_addr structure
    server_addr.sin_family = AF_INET;                // for TCP/IP
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // This HOST IP
    server_addr.sin_port = htons(SERVER_PORT);       // port number 1234
    printf("3 : bind socket to server address\n");
    r = bind(mysock, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if (r < 0)
    {
        printf("bind failed\n");
        exit(3);
    }
    printf(" hostname = %s port = %d\n", SERVER_HOST, SERVER_PORT);
    printf("4 : server is listening ....\n");
    listen(mysock, 5); // queue length = 5
    printf("=================== init done =======================\n");
}
int main()
{
    char line[MAX];
    server_init();
    while (1)
    { // Try to accept a client request
        printf("server: accepting new connection ....\n");
        // Try to accept a client connection as descriptor newsock
        len = sizeof(client_addr);
        csock = accept(mysock, (struct sockaddr *)&client_addr, &len);
        if (csock < 0)
        {
            printf("server: accept error\n");
            exit(1);
        }
        printf("server: accepted a client connection from\n");
        printf("---------------------------------------------–\n");
        printf("Clinet: IP=%s port=%d\n",
               inet_ntoa(client_addr.sin_addr),
               ntohs(client_addr.sin_port));
        printf("---------------------------------------------–\n");
        // Processing loop: client_sock <== data ==> client
        while (1)
        {
            n = read(csock, line, MAX);
            if (n == 0)
            {
                printf("server: client died, server loops\n");
                close(csock);
                break;
            }
            // show the line string
            printf("server: read n=%d bytes; line=%s\n", n, line);
            // echo line to client
            n = write(csock, line, MAX);
            printf("server: wrote n=%d bytes; ECHO=%s\n", n, line);
            printf("server: ready for next request\n");
        }
    }
}

  • client端代码
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#define MAX 256
#define SERVER_HOST "localhost"
#define SERVER_PORT 1234
struct sockaddr_in server_addr;
int sock, r;
int client_init()
{
    printf("======= clinet init ==========\n");
    printf("1 : create a TCP socket\n");
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
        printf("socket call failed\n");
        exit(1);
    }
    printf("2 : fill server_addr with server’s IP and PORT#\n");
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // localhost
    server_addr.sin_port = htons(SERVER_PORT);       // server port number
    printf("3 : connecting to server ....\n");
    r = connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if (r < 0)
    {
        printf("connect failed\n");
        exit(3);
    }
    printf("4 : connected OK to\n");
    printf("-------------------------------------------------------\n");
    printf("Server hostname=%s PORT=%d\n", SERVER_HOST, SERVER_PORT);
    printf("-------------------------------------------------------\n");
    printf("========= init done ==========\n");
}
int main()
{
    int n;
    char line[MAX], ans[MAX];
    client_init();
    printf("******** processing loop *********\n");
    while (1)
    {
        printf("input a line : ");
        bzero(line, MAX);           // zero out line[ ]
        fgets(line, MAX, stdin);    // get a line from stdin
        line[strlen(line) - 1] = 0; // kill \n at end
        if (line[0] == 0)           // exit if NULL line
            exit(0);
        // Send line to server
        n = write(sock, line, MAX);
        printf("client: wrote n=%d bytes; line=%s\n", n, line);
        // Read a line from sock and show it
        n = read(sock, ans, MAX);
        printf("client: read n=%d bytes; echo=%s\n", n, ans);
    }
}
  • 运行截图
    image
    image
posted @ 2021-11-28 20:53  PuTa0  阅读(71)  评论(0编辑  收藏  举报