一、不封装
server.c
/*
服务端程序,客户端成功连接后,会向本服务程序发送一个字符串,收到后需要回复,才能继续进行。
双方通过scanf从控制台获取字符串,来发送消息,当输入exit后退出程序
注意:客户端和服务端收到消息后,需要回复才能正常传输信息,因为recv函数会阻塞程序。
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
// 第1步:创建服务端的socket。
int listenfd;
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
return -1;
}
// 第2步:把服务端用于通信的地址和端口绑定到socket上。
struct sockaddr_in servaddr = {0}; // 服务端地址信息的数据结构。
servaddr.sin_family = AF_INET; // 协议族,在socket编程中只能是AF_INET。
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 任意ip地址。
//servaddr.sin_addr.s_addr = inet_addr("192.168.190.134"); // 指定ip地址。
servaddr.sin_port = htons(8080); // 指定通信端口。
if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
{
perror("bind");
close(listenfd);
return -1;
}
// 第3步:把socket设置为监听模式。
if (listen(listenfd, 5) != 0)
{
perror("listen");
close(listenfd);
return -1;
}
// 第4步:接受客户端的连接。
int clientfd; // 客户端的socket。
int socklen = sizeof(struct sockaddr_in); // struct sockaddr_in的大小
struct sockaddr_in clientaddr; // 客户端的地址信息。
clientfd = accept(listenfd, (struct sockaddr *)&clientaddr, (socklen_t *)&socklen);
printf("客户端(%s)已连接。\n", inet_ntoa(clientaddr.sin_addr));
// 第5步:与客户端通信,接收客户端发过来的报文后,回复ok。
char buffer[1024] = {0};
int iret;
while (1)
{
if ((iret = recv(clientfd, buffer, sizeof(buffer), 0)) <= 0) // 接收客户端的请求报文。
{
printf("iret=%d\n", iret);
break;
}
else
{
printf("recv message from:%s\n", buffer);
memset(buffer, '\0', sizeof(buffer));
scanf("%s", buffer); //从控制台获取字符串
if (strcmp(buffer, "exit") == 0)
break;
if ((iret = send(clientfd, buffer, strlen(buffer), 0)) <= 0) // 向客户端发送响应结果。
{
perror("send");
break;
}
memset(buffer, '\0', sizeof(buffer));
}
}
// 第6步:关闭socket,释放资源。
close(listenfd);
close(clientfd);
}
client.c
/*
客户端程序,连接服务器后,先向服务器发送一个 hello 消息,
双方通过scanf从控制台获取字符串,来发送消息,当输入exit后退出程序
注意:客户端和服务端收到消息后,需要回复才能正常传输信息,因为recv函数会阻塞程序。
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
// 第1步:创建客户端的socket。
int sockfd;
if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
perror("socket");
return -1;
}
struct sockaddr_in servaddr = {0};
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(8080); // 指定服务端的通信端口。
servaddr.sin_addr.s_addr = inet_addr("xxx"); //根据自己的情况修改
if (connect(sockfd, (struct sockaddr *)&servaddr, (socklen_t)(sizeof(servaddr))) != 0) // 向服务端发起连接清求。
{
perror("connect");
close(sockfd);
return -1;
}
// 第3步:与服务端通信,发送一个报文后等待回复,然后再发下一个报文。
int iret;
char buf[128] = "hello";
send(sockfd, buf, strlen(buf), 0);
while (1)
{
if ((iret = recv(sockfd, buf, sizeof(buf), 0)) <= 0) //接收服务端的回应报文。
{
printf("iret=%d\n", iret);
break;
}
else
{
printf("received msg from[%s]:%s\n", inet_ntoa(servaddr.sin_addr), buf); //打印出连接的客户端的ip和接收到的消息
memset(buf, '\0', sizeof(buf));
scanf("%s", buf); //从控制台获取字符串
if (strncmp(buf, "exit", 4) == 0)
break;
if ((iret = send(sockfd, buf, strlen(buf), 0)) <= 0) // 向服务端发送请求报文。
{
perror("send");
break;
}
memset(buf, '\0', sizeof(buf));
}
}
// 第4步:关闭socket,释放资源。
close(sockfd);
return 0;
}
二、c语言封装
封装头文件
client_server.h
#ifndef __CLIENT_SERVER_H
#define __CLIENT_SERVER_H
#include <arpa/inet.h>
int createsocket(int *fd);
int begconnect(int fd, const struct sockaddr *__addr);
int bind_listen(int listenfd, const struct sockaddr *__addr);
#endif
封装源程序
client_server.c
#include "client_server.h"
#include "stdio.h"
#include "unistd.h"
int createsocket(int *fd) //创建socket
{
if ((*fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
perror("socket");
return -1;
}
return 0;
}
int begconnect(int fd, const struct sockaddr *__addr) //开始连接服务程序
{
if (connect(fd, __addr, (socklen_t)(sizeof(*__addr))) != 0) // 向服务端发起连接清求。
{
perror("connect");
close(fd);
return -1;
}
return 0;
}
int bind_listen(int listenfd, const struct sockaddr *__addr) //服务端绑定ip和端口并开始监听
{
if (bind(listenfd, __addr, sizeof(*__addr)) != 0)
{
perror("bind");
close(listenfd);
return -1;
}
// 第3步:把socket设置为监听模式。
if (listen(listenfd, 5) != 0)
{
perror("listen");
close(listenfd);
return -1;
}
}
客户端应用程序
/*双方通过scanf从控制台获取字符串,来发送消息,当输入exit后退出程序
注意:客户端和服务端收到消息后,需要回复才能正常传输信息,因为recv函数会阻塞程序。*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "client_server.h"
int main(int argc, char *argv[])
{
// 第1步:创建客户端的socket。
int clientfd;
createsocket(&clientfd);
struct sockaddr_in servaddr = {0};
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(8080); // 指定服务端的通信端口。
servaddr.sin_addr.s_addr = inet_addr("xxxx"); //根据实际情况更改
begconnect(clientfd, (struct sockaddr *)&servaddr);
// 第3步:与服务端通信,发送一个报文后等待回复,然后再发下一个报文。
int iret;
char buf[128] = "hello";
send(clientfd, buf, strlen(buf), 0);
printf("fd=%d\n", clientfd);
while (1)
{
if ((iret = recv(clientfd, buf, sizeof(buf), 0)) <= 0) // 接收服务端的回应报文。
{
printf("iret=%d\n", iret);
break;
}
else
{
printf("received msg from[%s]:%s\n", inet_ntoa(servaddr.sin_addr), buf);
memset(buf, '\0', sizeof(buf));
scanf("%s", buf);
if (strncmp(buf, "exit", 4) == 0)
break;
if ((iret = send(clientfd, buf, strlen(buf), 0)) <= 0) // 向服务端发送请求报文。
{
perror("send");
break;
}
memset(buf, '\0', sizeof(buf));
}
}
// 第4步:关闭socket,释放资源。
close(clientfd);
return 0;
}
服务端应用程序
/*双方通过scanf从控制台获取字符串,来发送消息,当输入exit后退出程序
注意:客户端和服务端收到消息后,需要回复才能正常传输信息,因为recv函数会阻塞程序。*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "client_server.h"
int main(int argc, char *argv[])
{
// 第1步:创建服务端的socket。
int listenfd;
createsocket(&listenfd);
// 第2步:把服务端用于通信的地址和端口绑定到socket上。
struct sockaddr_in servaddr = {0}; // 服务端地址信息的数据结构。
servaddr.sin_family = AF_INET; // 协议族,在socket编程中只能是AF_INET。
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 任意ip地址。
//servaddr.sin_addr.s_addr = inet_addr("192.168.190.134"); // 指定ip地址。
servaddr.sin_port = htons(8080); // 指定通信端口。
bind_listen(listenfd, (const struct sockaddr *)&servaddr);
// 第4步:接受客户端的连接。
int clientfd; // 客户端的socket。
int socklen = sizeof(struct sockaddr_in); // struct sockaddr_in的大小
struct sockaddr_in clientaddr; // 客户端的地址信息。
clientfd = accept(listenfd, (struct sockaddr *)&clientaddr, (socklen_t *)&socklen);
printf("客户端(%s)已连接。\n", inet_ntoa(clientaddr.sin_addr));
// 第5步:与客户端通信,接收客户端发过来的报文后,回复ok。
char buffer[1024] = {0};
int iret;
printf("fd=%d\n", clientfd);
while (1)
{
if ((iret = recv(clientfd, buffer, sizeof(buffer), 0)) <= 0) // 接收客户端的请求报文。
{
printf("iret=%d\n", iret);
break;
}
else
{
printf("recv message from:%s\n", buffer);
memset(buffer, '\0', sizeof(buffer));
scanf("%s", buffer);
if (strcmp(buffer, "exit") == 0)
break;
if ((iret = send(clientfd, buffer, strlen(buffer), 0)) <= 0) // 向客户端发送响应结果。
{
perror("send");
break;
}
memset(buffer, '\0', sizeof(buffer));
}
}
// 第6步:关闭socket,释放资源。
close(listenfd);
close(clientfd);
}
三、c++封装
服务端封装头文件
#ifndef __SERVER_H
#define __SERVER_H
#include <arpa/inet.h>
class server
{
private:
int fd;
struct sockaddr_in addr;
public:
int newclientfd;
server(struct sockaddr_in *addr);
int createsocket(void);
int bind_listen(void);
int client_accept(struct sockaddr_in *addr);
int recvmsg(void *__buf, int len);
int sendmsd(const void *__buf, int len);
~server();
};
#endif
服务端封装源文件
#include "server.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
server::server(struct sockaddr_in *addr) //构造函数
{
this->addr = *addr;
this->newclientfd = -1;
this->fd = -1;
}
int server::createsocket(void) //创建socket
{
if ((this->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
perror("socket");
return -1;
}
return 0;
}
int server::bind_listen(void) //绑定端口开始监听
{
if (bind(this->fd, (const sockaddr *)&this->addr, (socklen_t)sizeof(this->addr)) != 0)
{
perror("bind");
close(this->fd);
return -1;
}
if (listen(this->fd, 5) != 0)
{
perror("listen");
close(this->fd);
return -1;
}
return 0;
}
int server::client_accept(struct sockaddr_in *addr) //接受客户端的连接请求
{
if (addr != nullptr)
{
int addrlen = sizeof(*addr);
this->newclientfd = accept(this->fd, (struct sockaddr *)addr, (socklen_t *)&addrlen);
if (this->newclientfd == -1)
{
perror("accept erro:");
return -1;
}
else
printf("客户端(%s)已连接。\n", inet_ntoa(addr->sin_addr));
}
return 0;
}
int server::recvmsg(void *__buf, int len) //接收消息
{
int readnum;
readnum = recv(this->newclientfd, __buf, len, 0);
return readnum;
}
int server::sendmsd(const void *__buf, int len) //发送消息
{
int sendnum;
sendnum = send(this->newclientfd, (char *)__buf, len, 0);
return sendnum;
}
server::~server() //析构函数,释放socket资源
{
if (this->fd >= 0)
close(this->fd);
if (this->newclientfd >= 0)
close(this->newclientfd);
}
服务端应用程序
/*双方通过scanf从控制台获取字符串,来发送消息,当输入exit后退出程序
注意:客户端和服务端收到消息后,需要回复才能正常传输信息,因为recv函数会阻塞程序。*/
#include "server.h"
#include <cstring>
#include <iostream>
int main()
{
struct sockaddr_in serveraddr = {0}; //sockaddr_in结构体
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(8080);
server server(&serveraddr); //创建server对象
if (server.createsocket() == -1) //创建socket
return -1;
if (server.bind_listen() == -1) //绑定ip和端口并开始监听
return -1;
struct sockaddr_in clientaddr; //创建要连接的客户端sockaddr_in结构体
if (server.client_accept(&clientaddr) == -1)
return -1;
char buf[128] = "hello"; //发送接收数据缓冲区
int iret;
while (1)
{
if ((iret = server.recvmsg(buf, sizeof(buf))) <= 0) // 接收服务端的回应报文。
{
printf("iret=%d\n", iret);
break;
}
else
{
std::cout << "received msg from " << inet_ntoa(clientaddr.sin_addr) << ":" << buf << std::endl; //打印连接的客户端ip和收到的消息
memset(buf, '\0', sizeof(buf));
std::cin.getline(buf, sizeof(buf)); //从控制台获取字符串
if (strncmp(buf, "exit", 4) == 0)
break;
if ((iret = server.sendmsd(buf, sizeof(buf))) <= 0) // 向服务端发送请求报文。
{
perror("send");
break;
}
memset(buf, '\0', sizeof(buf));
}
}
return 0;
}
客户端应用程序
/*双方通过scanf从控制台获取字符串,来发送消息,当输入exit后退出程序
注意:客户端和服务端收到消息后,需要回复才能正常传输信息,因为recv函数会阻塞程序。*/
#include "client.h"
#include <cstring>
#include <iostream>
int main()
{
struct sockaddr_in clientaddr;
clientaddr.sin_family = AF_INET;
clientaddr.sin_addr.s_addr = inet_addr("xxxx");
clientaddr.sin_port = htons(xxx);
client client(&clientaddr);
client.createsocket();
client.begconnect();
char buf[128] = {0};
int iret;
client.sendmsd("hello", 5);
while (1)
{
if ((iret = client.recvmsg(buf, sizeof(buf))) <= 0) // 接收服务端的回应报文。
{
printf("iret=%d\n", iret);
break;
}
else
{
std::cout << "received msg from " << inet_ntoa(clientaddr.sin_addr) << ":" << buf << std::endl;
memset(buf, '\0', sizeof(buf));
std::cin.getline(buf, sizeof(buf));
if (strncmp(buf, "exit", 4) == 0)
break;
if ((iret = client.sendmsd(buf, sizeof(buf))) <= 0) // 向服务端发送请求报文。
{
perror("send");
break;
}
memset(buf, '\0', sizeof(buf));
}
}
return 0;
}