TCP服务器 客户端 流程

本文详细介绍了TCP编程中,客户端和服务端的代码实现,包括创建套接字、连接服务器、绑定IP和端口、数据发送与接收等步骤,以及跨主机连接的注意事项。
摘要由CSDN通过智能技术生成

对于TCP的写作流程,分为对客户端代码的编写和服务端代码的编写
这两端的流程都是差不多的

对于TCP客户端的代码编写

第一步、首先需要创建属于客户端的TCP的套接字


PF_INET表示使用的是IPV4的网络,SOCK_STREAM表示使用的是TCP的流式套接字

int sock_fd = socket(PF_INET,SOCK_STREAM,0);
if(sock_fd==-1)
{
	perror("sock_fd error");
	return -1;
}

这里还需要判断套接字是否创建成功,创建失败返回-1

第二步、连接对应的服务器端,初始化对应的服务器的IP和端口


首先声明服务端结构
再设置对应的IP号和端口号
在连接到对应的服务端
这里的AF_INET和PF_INET是一样的,只是在套接字的使用时使用PF_INET,在结构体使用时使用AF_INET。

struct sockaddr_in serverAddr;
serverAddr.sin_family=AF_INET;
serverAddr.sin_port=2000;
serverAddr.sin_addr.s_addr="192.168.1.2";
int connect_ret=connect(sock_fd,(struct sockaddr_in *)&serverAddr,sizeof(serverAddr));
if(connect_ret==-1)
{
	perror("connect_ret error");
	return -1;
}

这里和上面一致需要看是否连接成功;
同时对端口和IP的设置可以上面这样设置,但只能在同一个主机或者同一个虚拟机中运行,不能访问到其他的主机,若需要访问到其他的主机则需要进行如下的设置:

serverAddr.sin_port=htons(12341);
serverAddr.sin_addr.s_addr=inet_addr("47.108.235.65");

这里的htons是主机转网络,将主机端口号转成网络端口号
这里的inet_addr是将主机IP转换成网络IP,这样就能实现对其他主机的连接了
你可能会问有没有网络转主机的呢?
当然有,ntohs()就是将网络端口号转换成主机端口号
同样的IP也有inet_network()就是将网络地址转换成主机地址,当然还有其他几个,这里没有用到就不赘述了

那么接下来就可以进行客户端到网络端的通信了


第三步、发送数据到服务端


首先定义一个buf存贮发送的数据,再通过send()函数发送到服务端

char buf[1024]={0};
while(1)
{
	memset(buf,0,sizeof(buf));
	printf("发送:\n");
	fgets(buf,sizeof(buf),stdin);
	send(sock_fd,buf,strlen(buf),0);
	printf("发送的数据:\n",buf);
}

第四步、就关闭套接字

close(sock_fd);

这样就实现了对TCP客户端代码的实现        

代码:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
int main(void)
{
	/*创建套接字*/
	int sock_fd=socket(PF_INET,SOCK_STREAM,0);
	if(sock_fd==-1)
	{
		printf("sock_fd error\n");
		return -1;
	}
	/*服务器的IP号和端口号*/
	struct sockaddr_in serverAddr;
	serverAddr.sin_family=AF_INET;
	serverAddr.sin_port=htons(12341);
	serverAddr.sin_addr.s_addr=inet_addr("47.108.235.65");
	int connet_s=connect(sock_fd,(struct sockaddr *)&serverAddr,sizeof(struct sockaddr_in));
	if(connet_s==-1)
	{
		printf("connet_s error\n");
		return -1;
	}
	/*发送数据*/
	char buf[1024]={0};
	while(1)
	{
		memset(buf,0,sizeof(buf));
		printf("发送:\n");
		fgets(buf,1024,stdin);
		send(sock_fd,buf,strlen(buf),0);
		printf("发送的数据:%s\n",buf);
	}
	/*关闭套接字*/
	close(sock_fd);
}

对于TCP服务端的代码编写


服务端的思路与客户端类似


第一步、首先需要创建属于服务端的TCP的套接字

int sock_fd = socket(PF_INET,SOCK_STREAM,0);
if(sock_fd==-1)
{
	perror("sock_fd error");
	return -1;
}

第二步、这就需要绑定自己(就是服务端)的IP和端口号,这里与客户端的区别就是多了一个绑定

struct sockaddr_in OwnAddr;
OwnAddr.sin_family=AF_INET;
OwnAddr.sin_port=htons(12341);
OwnAddr.sin_addr.s_addr=inet_addr("172.20.189.35");
bind(sock_fd,(struct sockaddr *)&OwnAddr,sizeof(OwnAddr));

第三步,设置监听,因为需要监听客户端是否发起连接或者是否发送数据

listen(sock_fd,5);

第四步、需要再次声明客户端的结构体,以及结构体大小,需要接收到客户端的IP和端口号以及数据

struct sockaddr_in ClientAddr;
int length=sizeof(struct sockaddr_in);

第五步、接收客户端的连接请求,并检查是否成功。

如果成功,它会返回一个新的套接字文件描述符;如果失败,它会输出一个错误消息并返回-1
然后在将连接的客户端的IP和端口号打印出来

int clientNew_fd=accept(sock_fd,(struct sockaddr *)&ClientAddr,&length);
if(clientNew_fd==-1)
{
	printf("clientNew_fd error\n");
	return -1;
}
printf("the costmer IP:%s ,the costmer port:%d\n",inet_ntoa(ClientAddr.sin_addr),ntohs(ClientAddr.sin_port));

第六步、就需要接收客户端发送的数据


需要定义buf接收数据 recv接收数据

char buf[1024]={0};
while(1)
{
	sleep(1);
	memset(buf,0,sizeof(buf));
	recv(clientNew_fd,buf,sizeof(buf),0);
	printf("the data:%s\n",buf);
}

第七步、关闭服务端套接字

close(sock_fd);
close(clientNew_fd);

这样服务端的代码就写完了

代码:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
int main(void)
{
	/*创建套接字*/
	int sock_fd=socket(PF_INET,SOCK_STREAM,0);
	if(sock_fd==-1)
	{
		printf("sock_fd error\n");
		return -1;
	}
	/*绑定自己的IP号和端口号*/
	struct sockaddr_in OwnAddr;
	OwnAddr.sin_family=AF_INET;
	OwnAddr.sin_port=htons(12341);//htons--->将主机端口号变成网络端口号 host to network short
	OwnAddr.sin_addr. s_addr=inet_addr("172.20.189.35");//inet_addr将主机IP转换为网络IP
	bind(sock_fd,(struct sockaddr *)&OwnAddr,sizeof(OwnAddr));
	/*设置监听*/
	listen(sock_fd,5);
	/*等待连接*/
	struct sockaddr_in ClientAddr;
	int length=sizeof(struct sockaddr_in);
	int clientNew_fd=accept(sock_fd,(struct sockaddr *)&ClientAddr,&length);
	if(clientNew_fd==-1)
	{
		printf("clientNew_fd error\n");
		return -1;
	}
	printf("the costmer IP:%s ,the costmer port:%d\n",inet_ntoa(ClientAddr.sin_addr),ntohs(ClientAddr.sin_port));
	/*接收数据*/
	char buf[1024]={0};
	while(1)
	{
		sleep(1);
		memset(buf,0,sizeof(buf));
		recv(clientNew_fd,buf,sizeof(buf),0);
		printf("the data:%s\n",buf);
	}
	/*关闭套接字*/
	close(sock_fd);
	close(clientNew_fd);
}

TCP(IP地址)(补)

如果服务器和客户端是在同一个主机上,如:使用Ubuntu系统中分别跑服务端和客户端,那么其IP地址必须一致,否则失败。

如果服务器和客户端是不在同一个主机上,情况一:一个主机与另一个主机,看那个主机作为服务器那个主机作为客户端,作为服务器的主机就设置自己的本地IP,作为客户端的主机就设置服务器的IP;情况二:一个主机和云服务器,将云服务器的IP地址设置为云服务器私网IP,客户端的地址设置为云服务器的公网IP。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值