2-23 TCP网络程序设计

(本节笔记的实验代码,在这里

1.  TCP编程模型函数化

        1.1  server端函数

                创建socket——>socket();
                绑定地址   ——>bind();
                监听端口   ——>listen();
                等待连接   ——>accept();
                接收数据   ——>recv();
                发送数据   ——>send();
                结束连接   ——>close();
        1.2  client端函数
                创建socket——> socket();
                连接服务器 ——>connect();
                接收数据   ——>recv();
                发送数据   ——>send();
                结束连接   ——>close();

2.  函数学习
    2.1创建套接字
        函数名:
                socket
        函数原型: man socket
                int socket(int domain, int type, int protocol);
        函数功能:
                创建网络套接字。
        所属头文件:
                <sys/types.h>         <sys/socket.h>
        返回值:
                成功 :返回int类型的sockfd         失败 :返回-1
        参数说明
                domain :AF_INET(IPV4因特网域)
                                   AF_INET6(IPV6因特网域)。
                type :SOCK_DGRAM(固定长度的无连接的不可靠的报文传输)
                             SOCK_RAW(IP协议的数据报接口,在POSIX.1中为可选)
                             SOCK_SEQPACKET(固定长度的有序的可靠的面向连接的报文传输)
SOCK_STREAM(有序的可靠的双向的面向连接的字节流)。
                protocol :通常是0。

    2.2  绑定地址
        函数名:
                bind
        函数原型: man 2 bind
                int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
        函数功能:
                将套接字与地址关联。
        所属头文件:
                <sys/types.h>         <sys/socket.h>
        返回值:
                成功 :返回0         失败 :返回-1
        参数说明
                sockfd :需要绑定的套接字ID。
                *addr :一个struct sockaddr结构的指针,里面存有server端地址。
                        //一般用法为(struct sockaddr *)(&struct sockaddr_in)
                addrlen :地址长度。
                /***********************************************************
                struct sockaddr{    //该结构是通用的地质类型,包括IPv4和IP6
                        sa_family_t sa_family;   //协议族
                        char sa_data[14];            //地址
                }
                struct sockaddr_in{   //该结构是IPv4专用地址结构
                        short int sin_family;          //协议族,AF_INET
                        unsigned short int sin_port;   //端口号,2字节
                        struct in_addr sin_addr;       //IPv4地址,4字节
                        unsigned char sin_zero[8];   //用0填充8字节   
                }
                struct in_addr{
                        unsigned long s_addr;      //一个长整形的地址数据,
                 }                                                      //需要把字符串转发为整形
                ***********************************************************
                in_addr_t inet_addr(const char *cp);
                <sys/socket.h> <netinet.in.h> <arpa/inet.h>
                功能:把字符串形式的IP地址转化为整形的IP地址(网络字节序)。
                范例:in_addr.s_addr = inet_addr ("192.168.0.1")

                char *inet_ntoa(struct in_addr);
                功能:把整形的IP地址转化为字符型的IP地址。
                ***********************************************************
                网络字节序:
                        网络上通讯过程中,需把发送到网络上的数据转化为网络字节序(大端模式数据),接收数据时,要把数据转化为主机字节序。
                <arpa/inet.h>
                uint32_t htonl(uint32_t hostlong);
                功能:将32位数据从主机字节序转化为网络字节序
                范例:in_addr.s_addr = htonl(INADDR_ANY);
                uint16_t htons(uint16_t hostshort);
                功能:将16位数据从主机字节序转化为网络字节序
                uint32_t ntohl(uint32_t netlong);
                功能:将32位数据从网络字节序转化为主机字节序
                uint16_t ntohs(uint16_t netshort);
                功能:将16位数据从网络字节序转化为主机字节序
                ***********************************************************/

    2.3  设置监听端口个数
        函数名:
                listen
        函数原型: man listen
                int listen(int sockfd, int backlog);
        函数功能:
                设置监听端口个数,表示服务器愿意接受连接请求。
        所属头文件:
                <sys/types.h>         <sys/socket.h>
        返回值:
                成功 :返回0         失败 :返回-1
        参数说明
                sockfd :server端套接字ID。

                backlog :server端愿意接受连接的个数。


    2.4  等待连接
        函数名:
                accept
        函数原型: man 2 accept
                int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
        函数功能:
                等待连接请求,接受并建立连接。若无连接请求则进入阻塞。
        所属头文件:
                <sys/types.h>         <sys/socket.h>
        返回值:
                成功 :返回新的sockfd         失败 :返回-1
        参数说明
                sockfd :server端的套接字ID。
                *addr :一个struct sockaddr结构的指针,里面存有client端地址。
                        //一般用法为(struct sockaddr *)(&struct sockaddr_in)
                *addrlen :client端地址长度(变量)的地址。


    2.5  接收数据
        函数名:
recv
        函数原型: man recv
                ssize_t recv(int sockfd, void *buf, size_t len, int flags);
        函数功能:
                控制如何接收数据。
        所属头文件:
                <sys/types.h>         <sys/socket.h>
        返回值:
                成功 :返回接收数据的大小         失败 :返回-1
        参数说明
                sockfd :accept函数返回的新的sockfd。
                *buf :接收的数据存放的地址。
                len :接收的数据大小。
                flags :标志位,如果不需要设置可以直接设为0。

    2.6发送数据
        函数名:
                send
        函数原型: man send
                ssize_t send(int sockfd, const void *buf, size_t len, int flags);
        函数功能:
                控制如何发送数据。
        所属头文件:
                <sys/types.h> <sys/socket.h>
        返回值:
                成功 :返回发送数据的大小 失败 :返回-1
        参数说明:
                sockfd :accept函数返回的新的sockfd。。
                *buf :需要发送的数据存放地址。
                len :发送数据的大小。
                flags :标志位,如果不需要设置可以直接设为0。

    2.7  关闭连接
        函数名:
                close
        函数原型: man close

                int close(int fd);

        函数功能:
                关闭连接。
        所属头文件:
                <unistd.h>
        返回值:
                成功 :返回0         失败 :返回-1
        参数说明
                fd :sockfd。

    2.8  连接服务器
        函数名:
                connect
        函数原型: man 
                int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
        函数功能:
                client端向server端请求建立连接。
        所属头文件:
                <sys/types.h>         <sys/socket.h>
        返回值:
                成功 :返回0         失败 :返回-1
        参数说明
                sockfd :client端sockid。
                *addr :一个struct sockaddr结构的指针,里面存有server端地址。
                         //一般用法为(struct sockaddr *)(&struct sockaddr_in)

                addrlen :client端地址长度。

3.  综合实例
/*  touch server.c  */

/* 利用TCP协议进行网络通讯的服务器端程序 */


#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>

#define PORTNUM 3333

int main()
{
int sockfd;
int app_sockfd;
int recv_sz;
long addr_len;
char buff[128];
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
/* 1.创建socket */
if(-1 == (sockfd = socket(AF_INET, SOCK_STREAM, 0)))
{
printf("create socket error!\n");
exit(1);
}
/* 2.绑定地址 */
bzero(&server_addr, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORTNUM);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr));
/* 3.监听端口 */
listen(sockfd, 5);
while(1)
{
addr_len = sizeof(struct sockaddr);
/* 4.等待连接 */
app_sockfd = accept(sockfd, (struct sockaddr *)(&client_addr), (socklen_t *)(&addr_len));
printf("server get connection from:%s\n", inet_ntoa(client_addr.sin_addr));
/* 5.接收数据 */
recv_sz = recv(app_sockfd, buff, 128, 0);
buffer[recv_sz] = '\0';
printf("server received %s\n", buff);
/* 6.结束连接 */
close(app_sockfd);
}
/* 7.结束连接 */
close(sockfd);
return 0;
}
                                                                  
/*  touch client.c  */

/* 利用TCP协议进行网络通讯的客户端程序 */


#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>

#define PORTNUM 3333


int main()
{
int sockfd;
int send_sz;
char buff[128];
struct sockaddr_in server_addr;
/* 1.创建socket */
if(-1 == (sockfd = socket(AF_INET, SOCK_STREAM, 0)))
{
printf("create socket error!\n");
exit(1);
}
/* 2.连接服务器 */
bzero(&server_addr, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORTNUM);
server_addr.sin_addr.s_addr = inet_addr("192.168.123.4");
if(-1 == connect(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr))
{
printf("connet fail!\n");
exit(1);
}
/* 4.发送数据 */
printf("Please input something:\n");
fgets(buff, 128, stdin);
send(sockfd, buffe, strlen(buffer), 0);
/* 5.结束连接 */
close(sockfd);
return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值