socket通信 tcp的客户端与服务端,双方能进行收发
socket通信 tcp的客户端与服务端,双方能进行收发
// server.c文件
// server.c
// 这是服务端代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>int listen_fd = -1;// 信号处理
void signal_handler(int arg)
{printf("close listen_fd(signal = %d)\n", arg);close(listen_fd);exit(0);
}int main(int argc, const char *argv[])
{int new_fd = -1;struct sockaddr_in server;struct sockaddr_in client;socklen_t saddrlen = sizeof(server);socklen_t caddrlen = sizeof(client);int net_mode;printf("set net mode\n");printf("1 default; 2 config by yourself\n");printf("please input: ");scanf("%d", &net_mode);//--------------------------手动配置,扫描终端输入进来的ip地址 和端口号//ip地址 最大长度为15,加 '\0'最大长度为 16字节//点分10进制char my_server_ip[16];unsigned int my_server_port; // 端口号 0~65535if( net_mode == 1){//-------------------------------进入默认 ip和端口配置FILE *fp;char *server_message;char *port;server_message = malloc(40);port = malloc(6);// 以可读可写方式打开文件fp = fopen("./config/net.conf", "r+");if (fp == NULL) {printf("Failed to open file");return EXIT_FAILURE;}fread(server_message, 40, 1, fp);// printf("%s\n", server_message);memcpy(my_server_ip, server_message+11, 14); //获取到 ip地址 printf("server ip is:%s\n", my_server_ip);memcpy(port, server_message+31, 5); //获取到 port printf("server port is:%s\n", port);my_server_port = atoi(port); // 转化为 unsigned int类型的 port号printf("\n======is %d\n", my_server_port);free(port); // 释放 portfree(server_message); // 释放 server_messagefclose(fp); // 关闭文件// 过程中 不需要输入 客户端ip地址和端口号}else if (net_mode == 2){printf("please input server ip: \n");scanf("%15s", my_server_ip);printf("input server port: \n");scanf("%d", &my_server_port);// 过程中 不需要输入 客户端ip地址和端口号}printf("server ip is:%s\n", my_server_ip);printf("\n======is %d\n", my_server_port);signal(SIGINT, signal_handler);memset(&server, 0, sizeof(server));memset(&client, 0, sizeof(client));// AF_INET 代表 ipv4协议// SOCK_STREAM 就代表着为 数据流协议,即为 tcp协议listen_fd = socket(AF_INET, SOCK_STREAM, 0);if (listen_fd < 0){printf("socket error!\n");return -1;}// 似乎这里只需要 server的 ip地址和端口号// AF_INET代表 ipv4协议server.sin_family = AF_INET;server.sin_port = htons(my_server_port);server.sin_addr.s_addr = inet_addr(my_server_ip);if (bind(listen_fd, (struct sockaddr *)&server, saddrlen) < 0){printf("bind error!\n");return -1;}if (listen(listen_fd, 4) < 0){printf("listen error!\n");return -1;}char connect_buf[20] = "connect success";char rbuf[256] = {0};int read_size = 0;char sendbuf[256] = {0};int send_size = 0;while (1){/*socket()创建的套接字默认是阻塞的,所以accept()在该套接字上进行监听时,如果没有客户端连接请求过来,accept()函数会一直阻塞等待;换句话说,程序就停在accept()函数这里,不会继续往下执行,直到有新的连接请求发送过来,唤醒accept()。*/new_fd = accept(listen_fd, (struct sockaddr *) &client, &caddrlen);if (new_fd < 0){perror("accept");return -1;}printf("new client connected.IP:%s,port:%u\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));send(new_fd, connect_buf, strlen(connect_buf)+1, 0); // 向客户端发送,连接成功的消息while (1){//--------------------------------------------------------------读 从客户端过来的信息read_size = recv(new_fd, rbuf, sizeof(rbuf), 0); // 读消息,最好用 sizeof(rbuf)if (read_size < 0){printf("read error!\n");continue;}else if (read_size == 0){printf("client (%d) is closed!\n", new_fd);close(new_fd);break;}printf("from client:%s", rbuf);if(strcmp(rbuf,"0x01\n") == 0){system("./bin/1.out");printf("\n");}else if(strcmp(rbuf,"0x02\n") == 0){printf("I like eat apple\n");}else if(strcmp(rbuf,"0x03\n") == 0){system("./bin/3.out");printf("\n");}else{printf("recv:%s\n", rbuf);}//-------------------------------------------------回复客户端消息printf("\n\ninput message to client:");scanf("%s", sendbuf);send(new_fd, sendbuf, strlen(sendbuf)+1, 0);printf("send:%s\n\n", sendbuf);memset(rbuf, 0, sizeof(rbuf));memset(sendbuf, 0, sizeof(sendbuf));}}close(listen_fd);return 0;
}
// config/net.conf文件
// config/net.conf内容
server_ip: 192.168.0.192
port: 9000
// client.c文件
// client.c
// 这里是 客户端代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>//#define SERVER_PORT 9000
//#define SERVER_IP "192.168.0.192" //服务器IP地址int main(int argc, const char *argv[])
{int connect_fd = -1;struct sockaddr_in server;socklen_t saddrlen = sizeof(server);//---------------------------------------------------------------扫描终端输入进来的ip地址 和端口号//ip地址 最大长度为15,加 '\0'最大长度为 16字节//点分10进制char my_server_ip[16];// 端口号 0~65535unsigned int my_server_port;printf("please input server ip: \n");scanf("%15s", my_server_ip);printf("input server port: \n");scanf("%d", &my_server_port);
//---------------------------------------------------------------扫描输入进来的ip地址 和端口号
// 过程中 不需要输入 客户端ip地址和端口号memset(&server, 0, sizeof(server));connect_fd = socket(AF_INET, SOCK_STREAM, 0);if (connect_fd < 0){printf("socket error!\n");return -1;}server.sin_family = AF_INET;server.sin_port = htons(my_server_port);//server.sin_port = htons(SERVER_PORT);server.sin_addr.s_addr = inet_addr(my_server_ip);//server.sin_addr.s_addr = inet_addr(SERVER_IP);if (connect(connect_fd, (struct sockaddr *)&server, saddrlen) < 0){printf("connect failed!\n\n");return -1;}//定义了 向服务端发送的bufchar buf[256] = {0};//定义了 读服务端的回复的bufchar rbuf[256] = {0};int read_size = 0;while (1){//--------------------------------------------------读从服务端过来的消息read_size = recv(connect_fd, rbuf, sizeof(rbuf), 0);//read_size = recv(connect_fd, rbuf, strlen(rbuf)+1, 0); // 用 strlen(rbuf)+1 会发现只能,接收到一个符号if (read_size <= 0){printf("message is null\n");//continue;}printf("\n\nrecv message from server: %s\n", rbuf);//--------------------------------------------------往服务端发消息printf("\n\ninput message to server:");fgets(buf, sizeof(buf), stdin);if (strcmp(buf, "quit\n") == 0){printf("client will quit!\n");break;}// 这里就用到了 我想用的 write函数// 往 客户端 文件描述符里写write(connect_fd, buf, sizeof(buf));printf("send message is: %s\n",buf);memset(rbuf, 0, sizeof(rbuf));memset(buf, 0, sizeof(buf));}close(connect_fd);return 0;
}