您的位置:首页 > 理论基础 > 计算机网络

Linux下socket编程之TCP简单实现

2017-05-02 14:35 645 查看
本文主要是简单的实现一个Linux下TCP网络编程的小例子。总共分为两个部分:客服端的实现和服务器端的实现。实现的功能很简单,当客服端和服务器端绑定之后,通过在客服端输入一个字符串,服务器将客服端输入的字符串进行相应的输出。

一、服务器端的实现

1、打开一个socket设备,获得socket设备的文件描述符,指定网络协议和传输类型

/* 1、获得服务器端的socket文件描述符 */
iSocketServerFd = socket(AF_INET, SOCK_STREAM, 0); // 网络协议是ipv4,传输方式为tcp
if(iSocketServerFd == -1)
{
printf("socket error!\n");
return -1;
} 2、绑定
主要是将第一步获得的文件描述符与具体的服务器端进行绑定,包括网络的协议、端口号、对客服端的访问限制等。

/* 2、对服务器端进行绑定 */
/* 2.1 设置服务器端的socket地址描述结构体 */
tSocketServerAddr.sin_family = AF_INET; // 网络协议是ipv4
tSocketServerAddr.sin_port = htons(SOCKET_PORT); // socket的端口号
tSocketServerAddr.sin_addr.s_addr = htonl(INADDR_ANY); // 客服端的地址可以是任意的
memset(tSocketServerAddr.sin_zero, 0, 8);

iSockAddrLen = sizeof(struct sockaddr); // 获得这个结构体的大小
/* 2.2 绑定 */
iRet = bind(iSocketServerFd, (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);
if(iRet == -1)
{
printf("bind error!\n");
return -1;
} 3、监听
对客服端进行监听。

/* 3、服务器端进行监听 */
iRet = listen(iSocketServerFd, LISTEN_BACKLOG);
if(iRet == -1)
{
printf("listen error!\n");
return -1;
} 4、accept

/* 4、接收一个客服端的socket的连接 */
iSocketClientFd = accept(iSocketServerFd, (struct sockaddr *)&tSocketClientAddr, &iSockAddrLen);
if(iSocketClientFd < 0)
{
printf("accept error!\n");
return -1;
}
5、接收和发送数据
/* 接收从客服端传送过来的数据 */
iRecvLen = recv(iSocketClientFd, ucRecvBuf, ARRAY_LENGTH, 0);
服务器端的完整实现代码如下:
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>

#define SOCKET_PORT		1234	// 定义端口,与指定的socket绑定
#define LISTEN_BACKLOG	10		// 最大监听的客服端数量
#define ARRAY_LENGTH	256		// 接收缓冲区的大小

/* 程序的入口函数 */
int main(void)
{
int iSocketServerFd;	// 定义服务器的文件描述符
int iSocketClientFd;	// 定义客服端的文件描述符

struct sockaddr_in tSocketServerAddr;	// 服务器socket地址的描述结构体定义
struct sockaddr_in tSocketClientAddr;	// 客服端socket地址的描述结构体定义

int iSockAddrLen;
int iRet;

unsigned char ucRecvBuf[ARRAY_LENGTH];	// 定义接收数据的缓冲区
int iRecvLen;

int client_flag = 0;

signal(SIGCHLD,SIG_IGN);

/* 1、获得服务器端的socket文件描述符 */
iSocketServerFd = socket(AF_INET, SOCK_STREAM, 0);	// 网络协议是ipv4,传输方式为tcp
if(iSocketServerFd == -1)
{
printf("socket error!\n");
return -1;
}

/* 2、对服务器端进行绑定 */
/* 2.1 设置服务器端的socket地址描述结构体 */
tSocketServerAddr.sin_family      = AF_INET;			// 网络协议是ipv4
tSocketServerAddr.sin_port        = htons(SOCKET_PORT);	// socket的端口号
tSocketServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);	// 客服端的地址可以是任意的
memset(tSocketServerAddr.sin_zero, 0, 8);

iSockAddrLen = sizeof(struct sockaddr);	// 获得这个结构体的大小

/* 2.2 绑定 */
iRet = bind(iSocketServerFd, (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);
if(iRet == -1)
{
printf("bind error!\n");
return -1;
}

/* 3、服务器端进行监听 */
iRet = listen(iSocketServerFd, LISTEN_BACKLOG);
if(iRet == -1)
{
printf("listen error!\n");
return -1;
}

while(1)
{
/* 4、接收一个客服端的socket的连接 */
iSocketClientFd = accept(iSocketServerFd, (struct sockaddr *)&tSocketClientAddr, &iSockAddrLen);
if(iSocketClientFd < 0)
{
printf("accept error!\n");
return -1;
}

client_flag = client_flag + 1;	// 更新标志位

/* 连接成功,打印出客服端的ip地址 */
printf("client %d : %s has connected\n", client_flag, inet_ntoa(tSocketClientAddr.sin_addr));

if(fork() == 0)		/*创建子进程*/
{
while(1)
{
/* 接收从客服端传送过来的数据 */
iRecvLen = recv(iSocketClientFd, ucRecvBuf, ARRAY_LENGTH, 0);
if(iRecvLen <= 0)
{
close(iSocketClientFd);
return -1;
}
else
{
ucRecvBuf[iRecvLen] = '\0';
printf("client %d : %s", client_flag, ucRecvBuf);
}
}
}
}

close(iSocketServerFd);
return 0;
}

二、客服端的实现

1、打开一个socket设备,获得设备描述符,指定网络协议和传输类型
/* 1、获得客服端的socket文件描述符 */
iSocketClientFd = socket(AF_INET, SOCK_STREAM, 0); // 网络协议是ipv4,传输类型为tcp
if(iSocketClientFd == -1)
{
printf("socket error!\n");
return -1;
} 2、connect
将客服端和服务器端连接起来。/* 2、初始化一个客服端和服务器之间的连接 */
/* 2.1 设置所连接的服务器 */
tSocketServerAddr.sin_family = AF_INET; // 协议是ipv4
tSocketServerAddr.sin_port = htons(SOCKET_PORT); // 绑定的端口
iRet = inet_aton(argv[1], &tSocketServerAddr.sin_addr); // 获得的ip地址
if(iRet == 0)
{
printf("server ip is not valid!\n");
return -1;
}
memset(tSocketServerAddr.sin_zero, 0, 8);

iSockAddrLen = sizeof(struct sockaddr);

/* 2.2 将客服端和服务器进行连接 */
iRet = connect(iSocketClientFd, (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);
if(iRet == -1)
{
printf("connect error!\n");
return -1;
}
3、接收和发送数据
if(fgets(ucSendBuf, ARRAY_LENGTH, stdin)) // 从用户输入获得一个字符串
{
/* 向客服端发送用户输入的信息 */
iSendLen = send(iSocketClientFd, ucSendBuf, strlen(ucSendBuf), 0);
if(iSendLen <= 0)
{
printf("send error!\n");
close(iSocketClientFd);
return -1;
}
}客服端的完整实现代码如下:
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SOCKET_PORT	1234	// 定义socket端口,用于可服务器端进行绑定
#define ARRAY_LENGTH	256		// 发送缓冲区的大小

int main(int argc, char **argv)
{
int iSocketClientFd; 	// 定义一个客服端的socket文件描述符

struct sockaddr_in tSocketServerAddr;	// 定义一个服务器端的socket地址描述结构体变量

int iSockAddrLen;
int iSendLen;
unsigned char ucSendBuf[ARRAY_LENGTH];	// 定义缓冲区
int iRet;

if(argc != 2)
{
printf("Usage :\n");
printf("%s <server_ip>\n", argv[0]);
return -1;
}

/* 1、获得客服端的socket文件描述符 */
iSocketClientFd = socket(AF_INET
4000
, SOCK_STREAM, 0);	// 网络协议是ipv4,传输类型为tcp
if(iSocketClientFd == -1)
{
printf("socket error!\n");
return -1;
}

/* 2、初始化一个客服端和服务器之间的连接 */
/* 2.1 设置所连接的服务器 */
tSocketServerAddr.sin_family      = AF_INET;			// 协议是ipv4
tSocketServerAddr.sin_port        = htons(SOCKET_PORT);	// 绑定的端口
iRet = inet_aton(argv[1], &tSocketServerAddr.sin_addr);	// 获得的ip地址
if(iRet == 0)
{
printf("server ip is not valid!\n");
return -1;
}
memset(tSocketServerAddr.sin_zero, 0, 8);

iSockAddrLen = sizeof(struct sockaddr);

/* 2.2 将客服端和服务器进行连接 */
iRet = connect(iSocketClientFd, (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);
if(iRet == -1)
{
printf("connect error!\n");
return -1;
}

printf("Input a message to %s: \n", argv[1]);
while(1)
{
if(fgets(ucSendBuf, ARRAY_LENGTH, stdin))	// 从用户输入获得一个字符串
{
/* 向客服端发送用户输入的信息 */
iSendLen = send(iSocketClientFd, ucSendBuf, strlen(ucSendBuf), 0);
if(iSendLen <= 0)
{
printf("send error!\n");
close(iSocketClientFd);
return -1;
}
}
}

close(iSocketClientFd);
return 0;
}

三、测试
由于本实例涉及到客服端和服务器,所以需要分别运行。可以在同一台电脑上进行测试,通过不同的终端来实现;也可以在不同的电脑上进行测试,只要在同一个局域网中即可。本次测试使用第一种方式进行。
测试结果如下:

客服端:



服务器端:



通过上面测试结果可以看出,每当在客服端输入一串字符串时,在相应的服务器端也会有同样的输出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux socket tcp