socket/tcp协议

        协议:
        计算机网络中实现通信必须有一定的约定,速率、传输代码、代码结构、传输控制步骤和出错控制等约定,约定称为通信协议。
        在两个节点之间要成功的通信,两个节点之间必须约定使用共同的语言,这些被通信各方共同遵守的约定、语言、规则被称为协议。
        在internet中,最为通用的网络协议是TCP/IP协议。
        OSI七层模型:
                  应用、表示、会话、传输、网络、数据链路、物理。
        TCP/IP四层模型:
                  应用、传输、网络、物理+数据链路。
                  TCP/IP实际上是一个一起工作的通信家族,为网络数据通信提供通路。
        TCP/IP协议簇为三个部分:
                  internet协议(IP)
                  传输控制协议(TCP)和用户数据报文协议(UDP)
                  处于TCP和UDP之上的一组协议专门开发的应用程序。远程登录(TELNET)、文件传输协议(FTP)、域名服务(DNS)和简单的邮件传送程序(SMTP)等许多协议。
                 

          //more /etc/services 查看端口绑定信息。


       完整socket:协议、本地地址、本地端口、远程地址、远程端口。

#include<sys/socket.h>   
int socket(int domain,int type,int protocal)                 
   返回:成功返回描述符,出错返回-1.
                    socket创建在内核中,若创建成功返回内核文件描述表中的socket描述符。实际上就是一个结构体。                   
 domin:                       
       AF_INET        IPv4网域            
       AF_INET6    IPv6网域                   
       AF_UNIX        nuix域                      
       AF_UNSPEC    未指定               
protocol:             
       通常为0,表示按给定的域和套接字类型选择默认协议。                   
 type:                    
        SOCK_STREAM                          
                 流式的套接字可以提供可靠的、面向连接的通讯流,它使用了TCP协议,TCP保证了数据传输的正确性和顺序性。                  
        SOCK_DGRAM                       
                 数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠,无差错。使用数据报协议UDP协议。       
        SOCK_RAW                        
                  原始套接字允许对底层协议如IP或者ICMP直接访问,主要用于新的网络协议实现的测试等。                     
      SOCK_SEQPACKET           
                 长度固定、有序、可靠的面向连接报文传递。



                  
                    网络传输的数据一定要统一顺序,所以对于内部字节表示顺序和网络字节顺序不同的机器,就一定要对数据进行转换。
                    uint32_t htonl(uint32_t hostlong)
                        将一个32位整数由主机字节序转换成网络字节序。
                    uint32_t htons(uint16_t hostlong)
                        将一个16位整数由主机字节序转换成网络字节序。
                    uint32_t ntohl(uint32_t hostlong)
                        将一个32位整数由网络字节序转换成主机字节序。
                    uint32_t ntohs(uint32_t hostlong)
                        将一个16位整数由网络字节序转换成主机字节序。

tcp服务器端:

/*************************************************************************
    > File Name: tcp_server.c
    > Author: CC
    > Mail: 6828620@163.com 
    > Created Time: 2018年10月21日 星期日 15时26分42秒
 ************************************************************************/
#include<arpa/inet.h>
#include<stdio.h>
#include<netdb.h>
#include<sys/socket.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<memory.h>
#include<signal.h>
#include<time.h>

int sockfd;

void sig_handler(int signo){
	if(signo == SIGINT){
		printf(" service close \n");
		close(sockfd);
		exit(1);
	}
}
//out client something
void out_addr(struct sockaddr_in *clientaddr)
{
	int port = ntohs(clientaddr->sin_port);
	char ip[16];
	memset(ip,0,sizeof(ip));
	//ip 从网络字节序转换成点分十进制
	inet_ntop(AF_INET,&clientaddr->sin_addr.s_addr,ip,sizeof(ip));
	printf("client: %s(%d) connected\n",ip,port);
}

void do_service(int fd)
{
	//获得系统时间
	long t = time(0);
	char *s = ctime(&t);
	size_t size = strlen(s) * sizeof(char);
	//服务器时间写回到客户端
	if(write(fd,s,size) != size){
		perror("write error!\n");
		exit(1);
	}

}

int main(int argc,char *argv[])
{
	if(argc < 2){
		printf("usage: %s #port\n",argv[0]);
		exit(1);
	}

	if(signal(SIGINT,sig_handler) == SIG_ERR){
		perror("signal sigint error");
		exit(1);
	}

	//创建socket,kernel,struct
	//AF_INET:ipv4
	//SOCK_STREAM:tcp协议
	//creat
	sockfd = socket(AF_INET,SOCK_STREAM,0);
	if(sockfd < 0){
		perror("socket error!\n");
		exit(1);
	}
	//bind
	//地址,端口设定后绑定
	struct sockaddr_in serveraddr;
	memset(&serveraddr,0,sizeof(serveraddr));
	//地址中填入ip,port,internet地址簇
	serveraddr.sin_family = AF_INET;//ipv4
	serveraddr.sin_port = htons(atoi(argv[1]));//端口
//	serveraddr.sin_addr.s_addr = "192.168.0.10";//指定单一地址相应
	serveraddr.sin_addr.s_addr = INADDR_ANY;//响应所有地址
	if(bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr)) < 0){
		perror("bind error");
		exit(1);
	}
	//listen
	//通知操作系统去接受来自客户端的链接请求
	//讲请求放置到10的大小队列当中
	if(listen(sockfd,10) < 0){
		perror("listen error");
		exit(1);
	}
	//accept
	//从队列中获得一个客户端的链接请求
	//若没有链接,则阻塞
	struct sockaddr_in clientaddr;
	socklen_t clientaddr_len = sizeof(clientaddr);
	while(1){
		int fd = accept(sockfd,(struct sockaddr*)&clientaddr,&clientaddr_len);
		if(fd < 0){
			perror("accept error!\n");
			continue;
		}
	//read write 
	out_addr(&clientaddr);
	do_service(fd);
	//close
	close(fd);
	return 0;
	}
}

tcp客户端:

/*************************************************************************
    > File Name: tcp_client.c
    > Author: CC
    > Mail: 6828620@163.com 
    > Created Time: 2018年10月21日 星期日 16时56分56秒
 ************************************************************************/
#include<arpa/inet.h>
#include<unistd.h>
#include<stdio.h>
#include<netdb.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<string.h>
#include<memory.h>

int main(int argc,char *argv[])
{
	if(argc < 3){
		printf("Usage : %s ip port \n",argv[0]);
		exit(1);
	}

	//创建
	int sockfd = socket(AF_INET,SOCK_STREAM,0);
	if(sockfd < 0){
		perror("socket ceart error!\n");
		exit(1);
	}
	//connect
	struct sockaddr_in serveraddr;
	memset(&serveraddr,0,sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(atoi(argv[2]));
	//将ip地址转换成网络字节序
	inet_pton(AF_INET,argv[1],&serveraddr.sin_addr.s_addr);
	if(connect(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr)) < 0){
		perror("connect error!\n");
		exit(1);
	}

	//read write
	char buffer[1024];
	memset(buffer,0,sizeof(buffer));
	size_t size;
	if((size = read(sockfd,buffer,sizeof(buffer))) < 0){
		perror("read error!\n");
		exit(1);
	}
	if(write(STDOUT_FILENO,buffer,size) != size){
		perror("writr error!");
	}
	close(sockfd);

	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雲烟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值