linux socket tcp

1. 概述:
该demo主要实现了linux下通过tcp方式的socket通讯,相关接口介绍可以参考<>
在这里插入图片描述

2. 场景(服务端(一)<----(一)客户端):
1) 服务端:
输入:服务端监听的port;
接收到客户端发送的消息,打印到终端,并且回复客户端"ok";
当接收消息内容为"exit"时,选择退出服务端进程
2) 客户端:
输入:客户端的port,以及服务端ip和port;
输入消息内容,将消息发送给服务端,阻塞直到接收到服务端的返回信息,并打印到终端(超时未接收到时,报错);
当输入消息内容为"exit"时,选择退出客户端进程

3. 测试:
TCP 服务端
在这里插入图片描述
客户端
在这里插入图片描述

/*
demo_tcp_client.c
网络编程demo(tcp客户端)*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include #include "lpm.h"void signal_func() { printf(RED BLINK"Server Close\n\n"NONE);
}int main(int argc, char **argv){int ret;int client_fd = -1;char client_port[8];char server_ip[32];char server_port[8];char buf[MAX_BUF];printf(RED BLINK"TCP 客户端\n"NONE);printf("请输入客户端 port\t");scanf("%s", client_port);printf("请输入服务端 ip  \t");scanf("%s", server_ip);printf("请输入服务端 port\t");scanf("%s", server_port);printf("\n");/*SIGPIPE : 在reader中止之后写Pipe的时候发送SIG_DFL : 默认信号处理程序SIG_IGN : 忽略信号的处理程序signal(SIGPIPE,SIG_IGN);对一个对端已经关闭的socket调用两次读/写, 第二次将会生成SIGPIPE信号, 该信号默认结束进程*/if(SIG_ERR == signal(SIGPIPE,signal_func)){perror("signal:");return -1;}/*协议域 : AF_INET(IPV4) AF_INET6(IPV6) AF_LOCAL AF_ROUTE 等等socket类型 : SOCK_STREAM(TCP) SOCK_DGRAM(UDP) 等等0 : 表示协议域和socket类型选择默认的协议, 通常是0*/client_fd = socket(AF_INET, SOCK_STREAM, 0);if(client_fd < 0){/*printf("socket:%s\n", strerror(errno));*/perror("socket:");return -1;}/*应用协议 : SOL_SOCKET(套接字) IPPROTO_TCP IPPROTO_IP...设置项 : SO_REUSEADDR(是否可以重用bind的地址)...opt : 一些设置项指的是开关...*/int opt = 1;ret = setsockopt(client_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt));if(ret < 0){perror("setsockopt");close(client_fd);return -1;}/*设置项 : SO_RCVTIMEO(为recv设置超时时间)...*/struct timeval tv;tv.tv_sec = RECV_TIME_OUT;tv.tv_usec = 0;ret = setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv));if(ret < 0){perror("setsockopt");close(client_fd);return -1;}struct sockaddr_in client_addr;memset(&client_addr, 0x0, sizeof(struct sockaddr_in));client_addr.sin_family = AF_INET;client_addr.sin_port = htons(atoi(client_port));client_addr.sin_addr.s_addr = htonl(INADDR_ANY);ret = bind(client_fd, (struct sockaddr*)&client_addr, sizeof(client_addr));if(ret < 0){perror("bind:");close(client_fd);return -1;}struct sockaddr_in server_addr;memset(&server_addr, 0x0, sizeof(struct sockaddr_in));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(atoi(server_port));inet_pton(AF_INET, server_ip, (void *)&(server_addr.sin_addr.s_addr));ret = connect(client_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));if(ret < 0){perror("connect:");close(client_fd);return -1;}memset(buf, 0x0, sizeof(buf));ret = recv(client_fd, buf, sizeof(buf), 0);if(ret > 0){printf("%s\n", buf);printf("\n");}else if(ret == 0){/* 无可用数据 或者 对等方已经按序结束 */printf(RED BLINK"Server Close\n\n"NONE);close(client_fd);return -1;}else if(ret < 0){perror("recv:");close(client_fd);return -1;}while(1){memset(buf, 0x0, sizeof(buf));printf("请输入消息\t");scanf("%s", buf);ret = send(client_fd, buf, strlen(buf), 0);if(ret < 0){perror("send:");continue;}if(strlen(buf) > 0 && strncmp(buf, EXIT, strlen(buf)) == 0){break;}memset(buf, 0x0, sizeof(buf));ret = recv(client_fd, buf, sizeof(buf), 0);if(ret > 0){printf("%s\n", buf);printf("\n");}else if(ret == 0){/* 无可用数据 或者 对等方已经按序结束 */printf(RED BLINK"Server Close\n\n"NONE);break;}else if(ret < 0){perror("recv:");continue;}}/*SHUT_RD(0) : 关闭sockfd上的读功能SHUT_WR(1) : 关闭sockfd的写功能SHUT_RDWR(2) : 关闭sockfd的读写功能*/shutdown(client_fd, SHUT_RDWR);close(client_fd);return 0;
}
/*
demo_tcp_server.c
网络编程demo(tcp服务端)*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include #include "lpm.h"void signal_func() { printf(RED BLINK"Client Close\n\n"NONE);
}int main(int argc, char **argv){int ret;int server_fd = -1;int connect_fd = -1;char server_port[8];char buf[MAX_BUF];printf(RED BLINK"TCP 服务端\n"NONE);printf("请输入服务端 port\t");scanf("%s", server_port);printf("\n");/*SIGPIPE : 在reader中止之后写Pipe的时候发送SIG_DFL : 默认信号处理程序SIG_IGN : 忽略信号的处理程序signal(SIGPIPE,SIG_IGN);对一个对端已经关闭的socket调用两次读/写, 第二次将会生成SIGPIPE信号, 该信号默认结束进程*/if(SIG_ERR == signal(SIGPIPE,signal_func)){perror("signal:");return -1;}/*协议域 : AF_INET(IPV4) AF_INET6(IPV6) AF_LOCAL AF_ROUTE 等等socket类型 : SOCK_STREAM(TCP) SOCK_DGRAM(UDP) 等等0 : 表示协议域和socket类型选择默认的协议, 通常是0*/server_fd = socket(AF_INET, SOCK_STREAM, 0);if(server_fd < 0){/*printf("socket:%s\n", strerror(errno));*/perror("socket:");return -1;}/*应用协议 : SOL_SOCKET(套接字) IPPROTO_TCP IPPROTO_IP...设置项 : SO_REUSEADDR(是否可以重用bind的地址)...opt : 一些设置项指的是开关...*/int opt = 1;ret = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt));if(ret < 0){perror("setsockopt");close(server_fd);return -1;}struct sockaddr_in server_addr;memset(&server_addr, 0x0, sizeof(struct sockaddr_in));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(atoi(server_port));server_addr.sin_addr.s_addr = htonl(INADDR_ANY);ret = bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));if(ret < 0){perror("bind:");close(server_fd);return -1;}ret = listen(server_fd, MAX_LISTEN);if(ret < 0){perror("listen:");close(server_fd);return -1;}char IP[32];int addrLen = sizeof(struct sockaddr);struct sockaddr_in client_addr;memset(&client_addr, 0x0, sizeof(struct sockaddr_in));connect_fd = accept(server_fd, (struct sockaddr *)&client_addr, (socklen_t *)&addrLen);if(connect_fd < 0){perror("accept:");close(server_fd);return -1;}memset(IP, 0x0, sizeof(IP));inet_ntop(AF_INET, (void *)&client_addr.sin_addr.s_addr, IP, sizeof(IP));printf("客户端 IP  \t%s\n", IP);printf("客户端 port\t%d\n", ntohs(client_addr.sin_port));printf("\n");ret = send(connect_fd, OK, strlen(OK), 0);if(ret < 0){perror("send:");close(connect_fd);close(server_fd);return -1;}while(1){memset(buf, 0x0, sizeof(buf));ret = recv(connect_fd, buf, sizeof(buf), 0);if(ret > 0){printf("消息      \t%s\n", buf);printf("\n");}else if(ret == 0){/* 无可用数据 或者 对等方已经按序结束 */printf(RED BLINK"Client Close\n\n"NONE);break;}else if(ret < 0){perror("recv:");continue;}if(strlen(buf) > 0 && strncmp(buf, EXIT, strlen(buf)) == 0){break;}ret = send(connect_fd, OK, strlen(OK), 0);if(ret < 0){perror("send:");continue;}}/*SHUT_RD(0) : 关闭sockfd上的读功能SHUT_WR(1) : 关闭sockfd的写功能SHUT_RDWR(2) : 关闭sockfd的读写功能*/shutdown(connect_fd, SHUT_RDWR);shutdown(server_fd, SHUT_RDWR);close(connect_fd);close(server_fd);return 0;
}
/*
lpm.h*/
#ifndef _LPM_H_#define _LPM_H_#define NONE            "\e[0m"
#define BLACK           "\e[0;30m"
#define L_BLACK         "\e[1;30m"
#define RED             "\e[0;31m"
#define L_RED           "\e[1;31m"
#define GREEN           "\e[0;32m"
#define L_GREEN         "\e[1;32m"
#define BROWN           "\e[0;33m"
#define YELLOW          "\e[1;33m"
#define BLUE            "\e[0;34m"
#define L_BLUE          "\e[1;34m"
#define PURPLE          "\e[0;35m"
#define L_PURPLE        "\e[1;35m"
#define CYAN            "\e[0;36m"
#define L_CYAN          "\e[1;36m"
#define GRAY            "\e[0;37m"
#define WHITE           "\e[1;37m" 
#define BOLD            "\e[1m"
#define UNDERLINE       "\e[4m"
#define BLINK           "\e[5m"
#define REVERSE         "\e[7m"
#define HIDE            "\e[8m"
#define CLEAR           "\e[2J"
#define CLRLINE         "\r\e[K" //or "\e[1K\r"#define MAX_BUF         64#define RECV_TIME_OUT   3#define MAX_LISTEN      1#define MAX_ACCEPT      2#define OK              "ok"#define EXIT            "exit"#define ERROR           "error"#define LOG()           printf("[%s %s] %s: %s: %d\n", __DATE__, __TIME__, __FILE__, __func__, __LINE__)#endif
#Makefile
CC := gcc
INCLUDE = -I /home/demo/include/all:$(CC) demo_tcp_server.c $(INCLUDE) -o demo_tcp_server -Wall -Werror$(CC) demo_tcp_client.c $(INCLUDE) -o demo_tcp_client -Wall -Werrorclean:rm demo_tcp_server demo_tcp_client


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部