Linux之网络编程

地址:ip+端口号

数据:协议(数据格式)

socket:

tcp:面向连接

udp:面向报文,不可靠,但数据量大

TCP/UDP对比
1.TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
2.TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
3.TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的
UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
4.每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信5. TCP首部开销20字节;UDP的首部开销小,只有8个字节
6.TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道
 


字节序


步骤 


API

ssize_t read(int fd, void *buf, size_t count);
       ssize_t write(int fd, const void *buf, size_t count);

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

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);

ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

socket服务器端代码demo

/*socket服务器端代码小demo*/
#include <stdio.h>
#include <sys/types.h>          
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

//int socket(int domain, int type, int protocol);创建套接字
//int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);为套接字绑定IP和端口号
//int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

int main(int argc,char **argv)
{
	int n_read;
	int so_fd;
	int clen;
	int cl_fd;
	char readBuf[128]={"\0"};
	char mesg[128] = {"\0"};	
	int mark = 0;	

	if(argc != 3){
		printf("too few arguments\n");
		exit(-1);
	}

	//1.socket创建套接字
	so_fd = socket(AF_INET,SOCK_STREAM,0);//IPV4因特网域,tcp协议,返回套接字描述符	
	if(so_fd == -1){
		perror("socket");
		exit(-1);
	}
	//2.bind绑定IP地址端口号
	struct sockaddr_in so_addr;
	memset(&so_addr,0,sizeof(struct sockaddr_in));//初始化数据为0
	so_addr.sin_family = AF_INET;//协议族,IPV4因特网域
	so_addr.sin_port = htons(atoi(argv[2]));//端口号,由主机转换成网络字节序
	inet_aton(argv[1],&so_addr.sin_addr);//IP地址,由字符串转换成网络格式
	bind(so_fd,(struct sockaddr*)&so_addr,sizeof(struct sockaddr_in));//结构体替换成另一个类型,但参数已经定义了类型,所以强转回原来的类型

	//3.listen监听
	listen(so_fd,10);

	//4.连接接受
	struct sockaddr_in cl_addr;
	clen = sizeof(struct sockaddr_in);

	while(1){
		memset(&cl_addr,0,sizeof(struct sockaddr_in));//初始化数据为0
		cl_fd = accept(so_fd,(struct sockaddr *)&cl_addr,&clen);//返回新建立通道fd,和客户端的信息
		if(cl_fd == -1){
			perror("accept");
		}else{
			printf("connect to client,IP:%s,port:%d\n",inet_ntoa(cl_addr.sin_addr),ntohs(cl_addr.sin_port));//网络格式IP转换成字符串形式
			}
	
		mark++;//标记接入客户端数

		if(fork() == 0){//创建子进程处理客户端,这样父进程可以继续等待其它客户端连接

			if(fork()==0){//创建子进程,让发送和接受信息能同时进行	

				while(1){	
					//5.read
					memset(readBuf,0,sizeof(readBuf));//清空数组里面的历史数据
					n_read = read(cl_fd,readBuf,128);//从客户端读取数据到数组缓冲区
					if(n_read == -1){
						perror("read");
					}else if(n_read > 0){
						printf("client:%d,%s\n",n_read,readBuf);//打印数据
					}else if(n_read == 0){
                        printf("client offline\n");//客户端关掉进程后发送FIN到服务端,然后系统给read函数发信号,告知read函数无数据,于是read函数马上返回0。
                        break;    
                    }
				}
			}

			while(1){
				//6.send
				sprintf(mesg,"Hello! NO.%d client\n",mark);
				write(cl_fd,mesg,strlen(mesg));//发数据到客户端
				sleep(8);
			}
		}
	}
	return 0;
}
/*client*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
//#include <linux/in.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

//int socket(int domain, int type, int protocol);创建套接字
//int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);为套接字绑定IP和端口号
//int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

int main(int argc,char **argv)
{
        int n_read;
        int cl_fd;
        char readBuf[128]={0};
        char mesg[128] = {0};

        if(argc != 3){
                printf("too few arguments\n");
                exit(-1);
        }

        //1.创建套接字
        cl_fd = socket(AF_INET,SOCK_STREAM,0);//IPV4因特网域,tcp协议,返回套接字描述符 
        if(cl_fd == -1){
                perror("socket");
                exit(-1);
        }
        //2.设置IP地址端口号
        struct sockaddr_in cl_addr;
        memset(&cl_addr,0,sizeof(struct sockaddr_in));//初始化数据为0
        cl_addr.sin_family = AF_INET;//协议族,IPV4因特网域
        cl_addr.sin_port = htons(atoi(argv[2]));//端口号,由主机转换成网络字节序
        inet_aton(argv[1],&cl_addr.sin_addr);//IP地址,由字符串转换成网络格式

        //3.连接
        int ret = connect(cl_fd,(struct sockaddr *)&cl_addr,sizeof(struct sockaddr_in));
        if(ret == -1){
                perror("connect");
                exit(-1);
        }

        while(1){
                if(fork()==0){//创建子进程,让发送和接受信息能同时进行  

                        while(1){
                                //4.read
                                memset(readBuf,0,sizeof(readBuf));//清空数组里面的历史数据
                                n_read = read(cl_fd,readBuf,128);//从服务器读取数据到数组缓冲区
                                if(n_read == -1){
                                        perror("read");
                                }else if(n_read >0){
                                        printf("server:%d,%s\n",n_read,readBuf);//打印服务器来的数据
                                }else if(n_read == 0){
                                        printf("server close\n");
                                        return 0;
                                }
                        }
                }

                while(1){
                        //5.send
                        memset(mesg,0,sizeof(mesg));
                        printf("input:\n");
                        gets(mesg);
                        write(cl_fd,mesg,strlen(mesg));//发数据到服务器
                }
        }
        return 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值