TCP简单实现(ipv4)

 

服务器端(server.c)

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

#define ERROR -1  //异常退出
#define NOR_MAL 1 //正常退出
#define Max 124

const ushort port = 49999;//端口号

static int server_fd;//服务器的文件描述符

//服务器的初始化
int server_init(ushort port)
{
	//建立流式套接字
    server_fd = socket(AF_INET,SOCK_STREAM,0);
    if(server_fd  == -1){
        perror("socket()");
        goto ERR_STEP;
    }
	//服务端的地址结构(ipv4)
	//htons进行大小端转化
	//INADDR_ANY表示任意ip地址,系统提供的宏
    struct sockaddr_in server_addr = {
                .sin_family        = AF_INET,
                .sin_port          = htons(port),
                .sin_addr.s_addr   = htonl(INADDR_ANY),
    };
	//服务端的地址长度
    socklen_t len = sizeof(server_addr);
	//绑定套接字,地址
    if(bind(server_fd,(struct sockaddr *)&server_addr,len) < 0){
        perror("bind");
        goto ERR_STEP;
    }
	//设置监听套接字,允许最大连接的套接字
    if(listen(server_fd,10) < 0){
        perror("listen");
        goto ERR_STEP;
    }
	//返回文件描述符
    return server_fd;

ERR_STEP:
    close(server_fd);
    return ERROR;

}


int main(int argc,char *argv[])
{
	//初始化
    int fd = server_init(port);
	//客户端的地址
    struct sockaddr_in client_addr;
	//客户端的地址长度
    socklen_t len = sizeof(client_addr);
    printf("waiting for conncet ...\n");
	//设置连接套接字
    int connfd = accept(fd,(struct sockaddr*)&client_addr,&len);
    if(fd < 0){
        perror("accept");
        goto ERR_STEP;
    }
	//打印客户端的ip地址和端口号
    printf("client ip is %s\n",inet_ntoa(client_addr.sin_addr));
    printf("client port is %u\n",ntohs(client_addr.sin_port));
	//循环接收数据
    while(1){
		//读缓冲区
        char readBuf[Max] = {0};
		//每次读取数据之前先清空缓冲区
        memset(readBuf,0,sizeof(readBuf));
		//读取数字,从连接套接字中读取,如果填写的不是connfd而是fd的话
		//读取数据的时候应该从客户端中读取
		//系统会报错,提示Transport endpoint is not connected
        int ret = read(connfd,readBuf,sizeof(readBuf)-1);
        if(ret > 0){//返回值大于0表示读取数据成功
            printf("%s\n",readBuf);
        }else if(ret == 0){//返回值为0的时候,表示客户端断开连接
            printf("the client is disconnect\n");
            goto ERR_STEP;
        }else {
            printf("recv failed\n");
            goto ERR_STEP;
         }
		 //当接收到的数据为quit的时候,结束退出
        int err = strncmp(readBuf,"quit",4);
        if(err == 0){
            printf("client is quit...\n");
            return NOR_MAL;
        }

    }
ERR_STEP:
    close(fd);
    return ERROR;
}

客户端实现(clinet.c)

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

#define ERROR -1
#define Max 124
//服务器的ip地址和端口号
//这里用的是回环地址,适用于同一台计算机上
//如果采用的是两台计算机,应该填充服务器的具体ip地址
const char *ip = "127.0.0.1";
const ushort port = 49999;

int main(int argc,const char *argv[])
{
	//建立流式套接字
    int server_fd = socket(AF_INET,SOCK_STREAM,0);
    if(server_fd  == -1){
        perror("socket()");
        goto ERR_STEP;
    }
	//服务器的地址结构
	//inet_addr将字符串形式的ip地址转换成网络字节序的整型值
    struct sockaddr_in server_addr 		= {
					.sin_family    		= AF_INET,
					.sin_port      		= htons(port),
					.sin_addr.s_addr    = inet_addr(ip),
    };
	//服务器的地址长度
    socklen_t len = sizeof(server_addr);
	//连接服务器
    if((connect(server_fd,(struct sockaddr*)&server_addr,len))< 0){
        perror("connect");
        goto ERR_STEP;
    }else{
        printf("connect successed\n");
    }
	//循环发送数据
    while(1){
		//写缓冲区
        char writeBuf[Max] = {0};
        memset(writeBuf,0,sizeof(writeBuf));
        scanf("%s",writeBuf);
        int ret = write(server_fd,writeBuf,strlen(writeBuf));
        if(ret < 0){
            perror("write");
            goto ERR_STEP;
        }
		//当输入quit的时候,客户端断开连接
        int err = strncmp(writeBuf,"quit",4);
        if(err == 0){
            printf("disconnet...\n");
            goto ERR_STEP;
        }
    }
ERR_STEP:
    close(server_fd);
    return ERROR;
	
}

运行:

服务器:gcc server.c -o s  (-o表示生成可执行文件)           

客户端:gcc client.c -o c

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值