LINUX系统编程__网络编程

进程间的通讯依赖于Linux内核,缺陷:无法多机通讯

Linux网络编程:

地址:IP地址、端口号;

数据:协议(数据格式):http、TCP/UDP客户端:ftp、http、socket

socket套接字 :TCP:面向连接(可靠);UDP:面向报文(不太可靠),数据量大,如视频

TCP/UDP的对比:

端口号的作用:

一台拥有IP地址的主机可以提供许多服务,比如web服务、FTP服务、SMTP服务等

这些服务完全可以通过一个IP来实现。主机是怎样区分不同的网络服务的?显然不能只靠IP地址,因为IP地址与网络服务的关系是一对多的关系。

实际上是通过IP地址加端口号来区分不同的服务的

端口通过了一种访问通道

服务器一般都是通过知名端口号来识别的。例如对于某个TCP/IP来说,FTP服务器的TCP端口号都是21,每个Telnet服务器的端口号都是23,每个TFTP(简单文件传输协议)服务器的UDP端口号都是69。

字节序:

字节序是指多字节数据在计算机内存中储存或者网络传输时各字节的储存顺序。

常见序:

Little endian 小端字节序:将低字节储存在起始地址

Big endian 大端字节序:将高字节储存在起始地址

网络字节序 = 大端字节序

字节序转换API

#include <arpa/inet.h>
uint16_t htons(uint16_t host16bitvalue);//返回网络字节序的值
uint32_t htonl(uint32_t host32bitvalue);//返回网络字节序的值
uint16_t ntohs(uint16_t net16bitvalue);//返回主机字节序的值
uint32_t ntohl(uint32_t net32bitvable);//返回主机字节序的值

h代表host,n代表net,s代表short(两个字节),l代表long(4个字节),通过上面的四个函数可以实现主机字节序和网络字节序之间的转换。有时可以用INASDDR_ANY,INADDR_ANY指定地址操作系统自己获取。

socket编程(服务器)

socket核心函数

#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>

int socket(int domain,int type,int protocl);
int bind(int sockfd,const struct sockaddr*my_addr,socklen_t addrlen);
int listen(int sockfd,int backlog);
int accept(int sockfd,struct sockaddr*addr,socklen_t*addlen);
int connect(int sockfd,const struct sockaddr*serv_addr,socklen_t addrlen);
int close(int fd);

1.指定连接协议(socket();)

2.地址准备好(bind();)

地址API转换

3.监听(listen();)

4.连接(accept();)

数据收发常用的第二套API

客户端的connect函数

服务端、客户端代码

服务端框架

telnet+IP+端口号进行连接

server.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>       
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
int main()
{
        int s_fd;
        int n_read;
        char readBuf[128];
        char *msg = "I get your connect!";
        struct sockaddr_in s_addr;
        struct sockaddr_in c_addr;

        memset(&s_addr,0,sizeof(struct sockaddr_in));
        memset(&c_addr,0,sizeof(struct sockaddr_in));
        //1.int socket(int domain, int type, int protocol);
        //创建一个socket
        s_fd = socket(AF_INET,SOCK_STREAM,0);
        if(s_fd == -1){
                perror("scoket");
                exit(-1);
        }
        //设置socket地址
        s_addr.sin_family = AF_INET;    //地址族:使用IPv4
        s_addr.sin_port = htons(8989);    //端口号,使用网络字节序表示
        inet_aton("192.168.66.66",&s_addr.sin_addr);    //IP地址v4地址,用网络字节序表示
        /*struct sockaddr_in
        {
        sa_family_t sin_family;    //地址族:AF_INET
        u_int16_t sin_port;        //端口号,要使用网络字节序表示
        struct in_addr sin_addr;   //IPv4地址结构体
        char sin_zero[8];          //不使用
        }
        struct in_addr
        {
            u_int32_t s_addr;   //IPv4地址,要用网络字节序表示
        }*/

        //分配地址信息,socket命名
        //2.int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
        bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

        //创建一个监听队列
        //3.int listen(int sockfd, int backlog);
        listen(s_fd,10);
        //连接
        //4.int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
        int clen = sizeof(struct sockaddr_in);    //大小
        int c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);    //强制转换,不然会有警告
        if(c_fd == -1){
                perror("accept");
        }
        printf("get connect:%s\n",inet_ntoa(c_addr.sin_addr));
        
        //读取
        //5.read
        n_read = read(c_fd,readBuf,128);
        if(n_read == -1){
                perror("read");
        }else{
                printf("get message:%d,%s\n",n_read,readBuf);
        }
        
        //写入
        //6.write
        write(c_fd,msg,strlen(msg));
        //7.close
        close(s_fd);    //关闭
        close(c_fd);

        return 0;
}

客户端框架

client.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
int main()
{
        int c_fd;
        int n_read;
        char readBuf[128];
        char *msg = "msg from client!";
        struct sockaddr_in c_addr;

        memset(&c_addr,0,sizeof(struct sockaddr_in));
        //1.int socket(int domain, int type, int protocol);

        c_fd = socket(AF_INET,SOCK_STREAM,0);
        if(c_fd == -1){
                perror("scoket");
                exit(-1);
        }

        c_addr.sin_family = AF_INET;
        c_addr.sin_port = htons(8989);
        inet_aton("192.168.31.41",&c_addr.sin_addr);

        /*struct sockaddr_in
                {
        sa_family_t sin_family;    //地址族:AF_INET
        u_int16_t sin_port;        //端口号,要使用网络字节序表示
        struct in_addr sin_addr;   //IPv4地址结构体
        char sin_zero[8];          //不使用
                }
        struct in_addr
        {
        u_int32_t s_addr;   //IPv4地址,要用网络字节序表示
        }*/
        
        //客户端不需要绑定和监听,直接连接服务器
        //2. int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
        if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1){    //连接
                perror("connect");
                exit(-1);
        }
        //3.send
        write(c_fd,msg,strlen(msg));
        //4.read
        n_read = read(c_fd,readBuf,128);
        if(n_read == -1){
                perror("read");
        }else{
                printf("get message from client : %d,%s\n",n_read,readBuf);
        }
        //5.close
        //关闭连接
        close(c_fd);
        return 0;
}

实现双方聊天

TCP服务端

server.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
int main(int argc,char **argv)    //传参   ./server IP 端口号
{
        int s_fd;
        int c_fd;
        int n_read;
        char readBuf[128] = {0};
        //char *msg = "I get your connect!";
        char msg[128] = {0};
        struct sockaddr_in s_addr;
        struct sockaddr_in c_addr;

        if(argc != 3){
                printf("param is not good\n");
                exit(-1);
        }
        memset(&s_addr,0,sizeof(struct sockaddr_in));
        memset(&c_addr,0,sizeof(struct sockaddr_in));
        //1.int socket(int domain, int type, int protocol);
        //创建一个socket
        s_fd = socket(AF_INET,SOCK_STREAM,0);
        if(s_fd == -1){
                perror("scoket");
                exit(-1);
        }
        //设置socket地址
        s_addr.sin_family = AF_INET;    //地址族:使用IPv4
        s_addr.sin_port = htons(atoi(argv[2]));    //端口号,使用网络字节序表示,atoi()将ASCII强制转换为int
        inet_aton(argv[1],&s_addr.sin_addr);    //IP地址v4地址,用网络字节序表示

        /*struct sockaddr_in
                {
        sa_family_t sin_family;    //地址族:AF_INET
        u_int16_t sin_port;        //端口号,要使用网络字节序表示
        struct in_addr sin_addr;   //IPv4地址结构体
        char sin_zero[8];          //不使用
                }
        struct in_addr
        {
        u_int32_t s_addr;   //IPv4地址,要用网络字节序表示
        }*/

        //分配地址信息,socket命名
        //2.int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
        bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
        
        //创建一个监听队列
        //3.int listen(int sockfd, int backlog);
        listen(s_fd,10);
        //连接
        //4.int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
        int clen = sizeof(struct sockaddr_in);
        while(1){    //不断的读取和写入
                c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);    //连接
                if(c_fd == -1){
                        perror("accept");
                        exit(-1);    //连接失败退出
                }
                printf("get connect:%s\n",inet_ntoa(c_addr.sin_addr));
                        if(fork() == 0){    //创建子进程,实现同时运行两个while(1)
                                //6.write
                                while(1){
                                        memset(msg,0,sizeof(msg));    //清除原始数据
                                        printf("input: \n");
                                        gets(msg);    //没输入时阻塞
                                        write(c_fd,msg,strlen(msg));    //将输入信息存入msg进行交互
                                }
                        }
                        //5.read
                        while(1){
                                memset(readBuf,0,sizeof(readBuf));    //清楚原始数据
                                //ssize_t read(int fd, void *buf, size_t count);
                                n_read = read(c_fd,readBuf,128);    //读取
                                if(n_read == -1){
                                        perror("read");
                                }else{
                                        printf("get message:%d,from client:%s\n",n_read,readBuf);
                                }
                        }
                        //7.close
                        close(s_fd);
                        close(c_fd);
        }
        return 0;
}

TCP客户端

client.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
int main(int argc,char **argv)
{
        int c_fd;
        int n_read;
        char readBuf[128];
        //char *msg = "msg from client!";
        char msg[128] = {0};
        struct sockaddr_in c_addr;

        if(argc != 3){
                printf("param is not good\n");
                exit(-1);
        }

        memset(&c_addr,0,sizeof(struct sockaddr_in));
        //1.int socket(int domain, int type, int protocol);

        c_fd = socket(AF_INET,SOCK_STREAM,0);
        if(c_fd == -1){
                perror("scoket");
                exit(-1);
        }

        c_addr.sin_family = AF_INET;
        c_addr.sin_port = htons(atoi(argv[2]));
        inet_aton(argv[1],&c_addr.sin_addr);

        /*struct sockaddr_in
                {
        sa_family_t sin_family;    //地址族:AF_INET
        u_int16_t sin_port;        //端口号,要使用网络字节序表示
        struct in_addr sin_addr;   //IPv4地址结构体
        char sin_zero[8];          //不使用
                }
        struct in_addr
        {
        u_int32_t s_addr;   //IPv4地址,要用网络字节序表示
        }*/
        //2. int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
        if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1){
                perror("connect");
                exit(-1);
        }
        while(1){    //不断进行读写操作
                if(fork() == 0){    //创建子进程
                        //3.send
                        while(1){
                                memset(msg,0,sizeof(msg));
                                printf("input: \n");
                                gets(msg);
                                write(c_fd,msg,strlen(msg));
                        }
                }
                while(1){
                        //4.read
                        memset(readBuf,0,sizeof(readBuf));
                        n_read = read(c_fd,readBuf,128);
                        if(n_read == -1){
                                perror("read");
                        }else{
                                printf("get message from client : %d,%s\n",n_read,readBuf);
                        }
                }
        }
        //5.close
        close(c_fd);
        return 0;
}

多方消息收发 ,TCP服务端

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
int main(int argc,char **argv)
{
        int s_fd;
        int c_fd;
        int n_read;
        int mark = 0;
        char readBuf[128] = {0};
        //char *msg = "I get your connect!";
        char msg[128] = {0};
        struct sockaddr_in s_addr;
        struct sockaddr_in c_addr;

        if(argc != 3){
                printf("param is not good\n");
                exit(-1);
        }
        memset(&s_addr,0,sizeof(struct sockaddr_in));
        memset(&c_addr,0,sizeof(struct sockaddr_in));
        //1.int socket(int domain, int type, int protocol);

        s_fd = socket(AF_INET,SOCK_STREAM,0);
        if(s_fd == -1){
                perror("scoket");
                exit(-1);
        }

        s_addr.sin_family = AF_INET;
        s_addr.sin_port = htons(atoi(argv[2]));
        inet_aton(argv[1],&s_addr.sin_addr);

        /*struct sockaddr_in
                {
        sa_family_t sin_family;    //地址族:AF_INET
        u_int16_t sin_port;        //端口号,要使用网络字节序表示
        struct in_addr sin_addr;   //IPv4地址结构体
        char sin_zero[8];          //不使用
                }
        struct in_addr
        {
        u_int32_t s_addr;   //IPv4地址,要用网络字节序表示
        }*/


        //2.int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
        bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

        //3.int listen(int sockfd, int backlog);
        listen(s_fd,10);
        //4.int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
        int clen = sizeof(struct sockaddr_in);
        while(1){
                c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);
                if(c_fd == -1){
                        perror("accept");
                }
                mark++;
                printf("get connect:%s\n",inet_ntoa(c_addr.sin_addr));
                if(fork() == 0){
                        if(fork() == 0){
                                //6.write
                                while(1){
                                        sprintf(msg,"welcom No.%d client",mark);
                                        write(c_fd,msg,strlen(msg));
                                        sleep(3);
                                }
                        }
                        //5.read
                        while(1){
                                memset(readBuf,0,sizeof(readBuf));
                                n_read = read(c_fd,readBuf,128);
                                if(n_read == -1){
                                        perror("read");
                                }else{
                                        printf("get message:%d,from client:%s\n",n_read,readBuf);
                                }
                        }
                        //7.close
                        close(s_fd);
                        close(c_fd);
                        break;
                }
        }
        return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值