实现现简单客户端和服务端的通信(基于TCP)
客户端代码如下
//client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <pthread.h>
#define SERV_PORT 9527
void my_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc, char *argv[])
{
int connect_fd;
char buf[BUFSIZ];
/*-------------- 1.创建表示绑定本地地址信息的socket -----------------*/
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET; //协议
server_addr.sin_port = htons(SERV_PORT); //字节顺序转换网络字节顺序
if (argv[1])
{ ////将点分十进制字符串转换为网络顺序IP地址
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
//method2
//inet_pton(AF_INET, "192.168.1.94", &server_addr.sin_addr.s_addr);
}
else
{
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
}
/*-------------------- 2.创建套接字对象 --------------------*/
if ( (connect_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
my_err("socket error");
}
/*-------------------- 3.尝试连接服务端 --------------------*/
//1.param1: socket返回地文件描述符.
//2.param2: socket储存连接地目的主机地址(包括IP地址和端口)
//3.param3:目的主机地址的长度
//4.如果连接成功返回0,失败则返回-1
if (connect(connect_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1)
{
my_err("connect error");
}
while (1)
{
//write(connect_fd, "hello\n", 6);
send(connect_fd, "hello\n", 6,0);
sleep(3);
int ret = read(connect_fd, buf, sizeof(buf));
printf("ret = %d\n", ret);
write(STDOUT_FILENO, buf, ret);//输出字符串
}
close(connect_fd);
return 0;
}
服务端代码如下
//server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <pthread.h>
#include <ctype.h>
#define SERV_PORT 9527
void my_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc, char *argv[])
{
int listen_fd, connect_fd;
char buf[BUFSIZ], client_ip[1024];
/*-------------- 1.创建表示绑定本地地址信息的sockaddr -----------------*/
//根据不同地应用,sockaddr需要选用不同地类型,IPV4网络通信选用sockaddr_in
struct sockaddr_in server_addr, client_addr;
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family = AF_INET; //选择协议簇
server_addr.sin_port = htons(SERV_PORT);//设置端口号
if (argv[1])
{
////将点分十进制字符串转换为网络顺序32位IP地址,大端模式
server_addr.sin_addr.s_addr = inet_addr(argv[1]); //设置IP地址
}
else
{
////否则设置为本地任意地址
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
}
/*-------------------- 2.创建套接字对象 --------------------*/
//param1:通信协议:IPV4协议簇
//param2:socket地类型:SOCK——STREAM, 可靠地,面向连接地流socket,默认为TCP
//param3:采用地协议:0,让系统自动选择默认协议
//如果成功,则返回一个打开的soeket文件描述符,失败则返回-1
if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
my_err("socket error");
}
/*------------------ 3.绑定本地ip地址和端口 -----------------*/
//param1:用于绑定IP信息和端口信息地socket文件描述符
//1.IP地址必须为本机IP地址
//2.端口必须为一个没有被占用地本地端口
if (bind(listen_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1)
{
my_err("bind error");
}
/*----------------------- 4.监听网络 ---------------------*/
//param1:绑定了IP信息和端口信息地socket文件描述符
//param2:请求排队地最大长度
if (listen(listen_fd, 128) == -1)
{
my_err("listen error");
}
/*------------------ 5.阻塞等待客户端连接响应 -----------------*/
// param1:绑定了IP信息和端口信息地socket文件描述符
// param2:用于存储客户端地IP地址和端口信息
// 返回一个新的文件描述符来标识该连接。如果执行失败,则返回-1
printf("wait for connect\n");
socklen_t len_client = sizeof(client_addr);
if ((connect_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &len_client)) == -1)
{
my_err("accept error");
}
else{
//打印客户端信息
printf("client : ip = %s, port = %d\n",
inet_ntop(AF_INET, &client_addr.sin_addr.s_addr, client_ip, sizeof(client_ip)),
ntohs(client_addr.sin_port));
}
while (1)
{
//如果执行成功,则返回读取数据的大小,失败则返回-1
int ret = read(connect_fd, buf, sizeof(buf));
write(STDOUT_FILENO, buf, ret);
sleep(3);
for (int i = 0; i < ret; i++)
{
buf[i] = toupper(buf[i]);
}
//printf("ret = %d\n", ret);
//如果执行成功,则返回发送数据地大小,失败则返回-1
write(connect_fd, buf, ret);
}
close(listen_fd);
close(connect_fd);
return 0;
}