Linux网络编程:socket编程(TCP、UDP)

TCP

TCP是面向连接字节流传输控制协议(面向连接就是互通之前先建立起连接),有验证重发机制,不会出现丢包或乱序;建立连接时有三次握手,取消连接时有四次挥手。三次握手就是两者进行一些约定,对格式的空间等信息进行传递。在用户层中提供的是数据,然后经过TCP协议添加了首部成为TCP段,再经过IP协议层添加了IP首部成为IP数据报,再到硬件驱动层添加以太网首部和以太网尾部成为以太网帧,TCP 报文头里面的序号能使 TCP 的数据按顺序到达;有累计确认及超时重传机制(时间加倍)。TCP主要传输重要数据(如文件),FTP属于TCP传输。
在这里插入图片描述

通信例程

服务器端
#include <sys/types.h>         
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>

#define SERVER_PORT 8888
#define BACKLOG 	10

int main(int argc,char **argv)
{
	int iSocketServer;
	int iSocketClient;
	struct sockaddr_in tSocketServerAddr;
	struct sockaddr_in tSocketClientAddr;
	int iRet;
	int iAddrLen;
	int iClientNum = -1;
	int iRecvLen;
	unsigned char ucRecvBuf[1000];
	
	
	signal(SIGCHLD,SIG_IGN);

	// 获得文件句柄
	iSocketServer = socket(AF_INET,SOCK_STREAM,0);
	if(-1 == iSocketServer)
	{
		printf("socket error!\n");
		return -1;
	}

	// 配置本地信息
	tSocketServerAddr.sin_family = AF_INET;			// Ipv4协议
	tSocketServerAddr.sin_port = htons(SERVER_PORT); // 设置端口
	tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;	// 允许任何地址
	memset(tSocketServerAddr.sin_zero,0,8);

	// 传递前面构造的结构体
	iRet = bind(iSocketServer,
				(const struct sockaddr *)&tSocketServerAddr,
				sizeof(struct sockaddr));
	if(-1 == iRet)
	{
		printf("bind error!\n");
		return 0;
	}

	// 监听信息
	iRet = listen(iSocketServer,BACKLOG);
	if(-1 == iRet)
	{
		printf("listen error!\n");
		return -1;
	}
	
	while(1)
	{
		iAddrLen = sizeof(struct sockaddr);
		// 获取客户端信息
		iSocketClient = accept(iSocketServer,
						(struct sockaddr *)&tSocketClientAddr,
						&iAddrLen);
		if(-1 != iSocketClient)
		{
			iClientNum++;
			printf("Get connect from client %d : %s\n",
					iClientNum,
					inet_ntoa(tSocketClientAddr.sin_addr));
			if(!fork())
			{
				while(1)
				{
					// send/recv发送接收信息
					iRecvLen = recv(iSocketClient,ucRecvBuf,999,0);
					if(iRecvLen <= 0)
					{
						close(iSocketClient);
						return -1;
					}
					else
					{
						ucRecvBuf[iRecvLen]='\0';
						printf("Get Msg From Client %d : %s",
								iClientNum,ucRecvBuf);
					}
				}
			}
		}
	}
	close(iSocketClient);
	return 0;
}
客户端
#include <sys/types.h>       
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>


#define SERVER_PORT 8888

int main(int argc,char **argv)
{
	int iSocketClient;
	struct sockaddr_in tSocketServerAddr;
	int iRet;
	unsigned char ucSendBuf[1000];
	int iSendlen;
	
	if(argc != 2)
	{
		printf("Usage:\n");
		printf("%s <server_ip>\n",argv[0]);
		return -1;
	}
	// 打开获得句柄
	iSocketClient = socket(AF_INET, SOCK_STREAM, 0);

	tSocketServerAddr.sin_family	 = AF_INET;
	tSocketServerAddr.sin_port		 = htons(SERVER_PORT);
	if(0 == inet_aton(argv[1],&tSocketServerAddr.sin_addr))
	{
		printf("invalid server_ip\n");
		return -1;
	}
	memset(tSocketServerAddr.sin_zero, 0, 8);

	// 与服务器端建立连接
	iRet = connect(iSocketClient, 
					(const struct sockaddr *)&tSocketServerAddr,
					sizeof(struct sockaddr));
	if(-1 == iRet)
	{
		printf("connect error!\n");
		return -1;
	}
	while(1)
	{
		if(fgets(ucSendBuf,999,stdin))
		{
			// 发送接收信息
			iSendlen = send(iSocketClient,
							ucSendBuf,strlen(ucSendBuf),0);
			if(iSendlen <= 0)
			{
				close(iSocketClient);
				return -1;
			}
		}
	}
	return 0;
}

UDP

UDP是无连接数据报服务,不对数据包进行检查、无需等待对方应答,会出现丢包乱序,但具有较好的实时性,比TCP结构简单,适用直播、游戏、物联网等实时性比较高的传输。TFTP、DHCP属于UDP的一种。
在这里插入图片描述

通信例程

服务器端

(注意对比一下TCP的例程)

#include <sys/types.h>         
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>

#define SERVER_PORT 8888

int main(int argc,char **argv)
{
	int iSocketServer;
	int iSocketClient;
	struct sockaddr_in tSocketServerAddr;
	struct sockaddr_in tSocketClientAddr;
	int iRet;
	int iAddrLen;
	int iClientNum = -1;
	int iRecvLen;
	unsigned char ucRecvBuf[1000];
	
	
	signal(SIGCHLD,SIG_IGN);

	// 打开获得句柄
	iSocketServer = socket(AF_INET,SOCK_DGRAM,0);
	if(-1 == iSocketServer)
	{
		printf("socket error!\n");
		return -1;
	}

	// 配置本地信息
	tSocketServerAddr.sin_family	  = AF_INET;
	tSocketServerAddr.sin_port		  = htons(SERVER_PORT);
	tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
	memset(tSocketServerAddr.sin_zero,0,8);

	// 传递前面构造的结构体
	iRet = bind(iSocketServer,
				(const struct sockaddr *)&tSocketServerAddr,
				sizeof(struct sockaddr));
	if(-1 == iRet)
	{
		printf("bind error!\n");
		return -1;
	}

	while(1)
	{
		iAddrLen = sizeof(struct sockaddr);
		
		// 发送/接收信息
		iRecvLen = recvfrom(iSocketServer, ucRecvBuf, 999, 0, 
					(struct sockaddr *)&tSocketClientAddr, &iAddrLen);
		if(iRecvLen > 0)
		{
			ucRecvBuf[iRecvLen] = '\0';
			printf("Get Msg From %s : %s\n", 
					inet_ntoa(tSocketClientAddr.sin_addr), ucRecvBuf);
		}
		
	}
	close(iSocketClient);
	return 0;
}
客户端
#include <sys/types.h>       
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>

#define SERVER_PORT 8888

int main(int argc,char **argv)
{
	int iSocketClient;
	struct sockaddr_in tSocketServerAddr;
	int iRet;
	unsigned char ucSendBuf[1000];
	int iSendLen;
	int iAddrLen;
	
	if(argc != 2)
	{
		printf("Usage:\n");
		printf("%s <server_ip>\n",argv[0]);
		return -1;
	}
	// 打开获得句柄
	iSocketClient = socket(AF_INET, SOCK_DGRAM, 0);

	tSocketServerAddr.sin_family	 = AF_INET;
	tSocketServerAddr.sin_port		 = htons(SERVER_PORT);
	if(0 == inet_aton(argv[1],&tSocketServerAddr.sin_addr))
	{
		printf("invalid server_ip\n");
		return -1;
	}
	memset(tSocketServerAddr.sin_zero, 0, 8);

	while(1)
	{
		if(fgets(ucSendBuf,999,stdin))
		{
			iAddrLen = sizeof(struct sockaddr);
			
			// 发送/接收信息
			iSendLen = sendto(iSocketClient, ucSendBuf, 
								strlen(ucSendBuf), 0, 
							(const struct sockaddr *)&tSocketServerAddr, 
								iAddrLen);
			if(iSendLen <= 0)
			{
				close(iSocketClient);
				return -1;
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

R-QWERT

你的鼓励是我最大的动力!

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

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

打赏作者

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

抵扣说明:

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

余额充值