Socket编程下篇-----TCP协议的C/S案例

本文介绍了一个简单的TCP网络编程实例,包括服务器端和服务端的源码实现。通过四个核心文件,详细展示了如何创建、绑定、监听及接收客户端连接,并实现基本的数据收发功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一共有4个源码文件组成。

tcp_net_socket.h源码:

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

extern int tcp_init(const char* ip, int port);
extern int tcp_accept(int sfd);
extern int tcp_connect(const char* ip, int port);
extern void signalhandler(void);
#endif

tcp_net_socket.c源码:

#include "tcp_net_socket.h"

//用于初始化,返回一个经过bind、listen处理以后的socket
int tcp_init(const char* ip, int port)
{
	//首先创建一个Socket,向系统申请
	int sfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sfd == -1)
	{
		perror("server socket");
		exit(-1);
	}
	
	struct sockaddr_in serveraddr;
	memset(&serveraddr, 0, sizeof(struct sockaddr));
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(port);
	serveraddr.sin_addr.s_addr = inet_addr(ip);
	
	//将新的socket与指定的ip、port绑定
	if(bind(sfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr))==-1)
	{
		perror("bind");
		close(sfd);
		exit(-1);
	}
	
	//监听它,并设置其允许最大的连接数为10个
	if(listen(sfd, 10) == -1)
	{
		perror("listen");
		close(sfd);
		exit(-1);
	}
	return sfd;
}

//用于服务端的接收,返回一个经过accept处理以后的new_fd
int tcp_accept(int sfd)
{
	struct sockaddr_in clientaddr;
	memset(&clientaddr, 0, sizeof(struct sockaddr));
	int addrlen = sizeof(struct sockaddr);
	int new_fd = accept(sfd, (struct sockaddr*)&clientaddr, &addrlen);
	//sfd接受客户端连接,并创建新的socket为new_fd,将请求连接的客户端的IP、port保存在结构体clientaddr中
	if(new_fd == -1)
	{
		perror("accept");
		close(sfd);
		exit(-1);
	}
	printf("success connect......\n");
	return new_fd;
}

//用于客户端连接
int tcp_connect(const char* ip, int port)
{
	int sfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sfd == -1)
	{
		perror("client socket");
		exit(-1);
	}
	
	struct sockaddr_in serveraddr;
	memset(&serveraddr, 0, sizeof(struct sockaddr));
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(port);
	serveraddr.sin_addr.s_addr = inet_addr(ip);
	//将sfd连接到指定服务器网络地址serveraddr
	if(connect(sfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr))==-1)
	{
		perror("connect");
		close(sfd);
		exit(-1);
	}
	return sfd;
}

//用于信号处理,让服务端在按下Ctrl+c或Ctrl+\时不会退出
void signalhandler(void)
{
	sigset_t sigSet;
	sigemptyset(&sigSet);
	sigaddset(&sigSet, SIGINT);
	sigaddset(&sigSet, SIGQUIT);
	sigprocmask(SIG_BLOCK, &sigSet, NULL);
}

tcp_net_server.c源码:

#include "tcp_net_socket.h"

int main(int argc, char* argv[])
{
	if(argc < 3)
	{
		printf("用法:./tcp_net_server ip port\n");
		exit(-1);
	}
	
	signalhandler();
	int sfd = tcp_init(argv[1], atoi(argv[2]));
	
	//用while循环表示可以与多个客户端接收和发送,但是仍是阻塞模式
	while(1)
	{
		int connected_fd = tcp_accept(sfd);
		char buf[512] = {0};
		//从connected_fd客户端接收数据存储于buf中
		if(recv(connected_fd, buf, sizeof(buf), 0)==-1)
		{
			perror("server recv");
			close(connected_fd);
			close(sfd);
			exit(-1);
		}
		puts(buf);
		//向connected_fd客户端发送hello world数据
		if(send(connected_fd, "hello world", 12, 0) == -1)
		{
			perror("server send");
			close(connected_fd);
			close(sfd);
			exit(-1);
		}
		//每个客户端完成一次发送接收,就把客户端连接资源释放。
		close(connected_fd);
	}
	close(sfd);
	return 0;
}

tcp_net_client.c源码:

#include "tcp_net_socket.h"

int main(int argc, char* argv[])
{
	if(argc < 3)
	{
		printf("用法:./tcp_net_client ip port\n");
		exit(-1);
	}
	
	int sfd = tcp_connect(argv[1], atoi(argv[2]));
	char buf[512] = {0};
	send(sfd, "hello", 6, 0);
	recv(sfd, buf, sizeof(buf), 0);
	puts(buf);
	close(sfd);
}

调试程序:

//编译程序
gcc -o tcp_net_server tcp_net_server.c tcp_net_socket.c
gcc -o tcp_net_client tcp_net_client.c tcp_net_socket.c
//运行程序
./tcp_net_server 172.16.125.150 8888
./tcp_net_client 172.16.125.150 8888

此处的ip最好填写本机IP,端口号填写大于1024的整数就好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值