嵌入式linux socket模块 TCP代码解析

sever

#include <sys/types.h>          /* See NOTES */
#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>


/* socket
 * bind
 * listen
 * accept
 * send/recv
 */

#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 iRecvLen;
	unsigned char ucRecvBuf[1000];

	int iClientNum = -1;
		//0、子进程关闭僵死解决函数
	signal(SIGCHLD,SIG_IGN);
	/*1、 socket(domain, type,protocol ):
	domain 指定套接字的协议族 常见AF_INET(IPv4)和AF_INET6(IPv6);
type:指定套接字的类型,常见的有SOCK_STREAM(流式套接字,用于TCP协议)和SOCK_DGRAM(数据报套接字,用于UDP协议)
protocol:指定套接字所使用的协议,通常为0 */
	iSocketServer = socket(AF_INET, SOCK_STREAM, 0);
	if (-1 == iSocketServer)
	{
		printf("socket error!\n");
		return -1;
	}
	
	/*2、初始化bind地址结构体
	
		两种结构体一样大小,sockaddr_in为sockaddr的数据进一步分析
		struct sockaddr{
		unisgned short as_family;
		char sa_data[14];
		};
	
		
		struct sockaddr_in{
		unsigned short sin_family;sin_family 一般为 AF_INET(ipv4)
		unsigned short sin_port;
		struct in_addr sin_addr; sin_addr 设置为 INADDR_ANY 表示可以和任何的主机通信
		unsigned char sin_zero[8];
		}

		*/
	tSocketServerAddr.sin_family      = AF_INET;
	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
 	tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
	memset(tSocketServerAddr.sin_zero, 0, 8);
	
	/* 3、int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
sockfd:套接字描述符,即通过socket函数创建的套接字
addr:指向要绑定的本地地址的指针,通常是一个struct sockaddr类型的结构体指针(IP 端口)
addrlen:本地地址的长度,即addr指向的结构体的大小 
*/
	iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));
	if (-1 == iRet)
	{
		printf("bind error!\n");
		return -1;
	}
	
	//4、listen(监听IP端口),BACKLOG为同时监听的路数
	iRet = listen(iSocketServer, BACKLOG);
	if (-1 == iRet)
	{
		printf("listen error!\n");
		return -1;
	}

	while (1)
	{
		iAddrLen = sizeof(struct sockaddr);
		
		//5、等待client的连接,把client的地址信息保存在tSocketClientAddr,注意第三个参数是地址长度的指针
		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));

			/*6、每来一个连接,都创建一个进程,注意这里是复制出另一个进程,
			新创建的进程执行if函数体,原来的进程不执行if函数体*/
			if (!fork())
			{
				/* 子进程的源码 */
				while (1)
				{
					/* 7、接收客户端发来的数据并显示出来 
					recv(sockfd, buf, len, flags)
					flag : 0:默认标志位,表示普通的阻塞式接收操作。
					MSG_DONTWAIT:非阻塞模式,即使没有数据可接收也会立即返回。
					MSG_PEEK:查看数据,但不从缓冲区中移除数据。
				*/
					iRecvLen = recv(iSocketClient, ucRecvBuf, 999, 0);
					if (iRecvLen <= 0)
					{
						close(iSocketClient);
						return -1;
					}
					else
					{
						ucRecvBuf[iRecvLen] = '\0';
						printf("Get Msg From Client %d: %s\n", iClientNum, ucRecvBuf);
					}
				}				
			}
		}
	}
	
	close(iSocketServer);
	return 0;
}


client

#include <sys/types.h>          /* See NOTES */
#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>

/* socket
 * connect
 * send/recv
 */

#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);  /* host to net, short */
 	//tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
 	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;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值