一、关键字
不同PC的进程间通信、OSI系统模型、TCP/IP系统模型、TCP/IP协议、TCP数据包格式、网络解包和封包过程、网络字节序、套接字
二、基于TCP/IP的socket通信
1.服务器端流程及接口展示
创建socket监听套接字文件描述符
/**********************************************************
*函数功能:创建一个套接字文件描述符
*参数: domain:协议族(AF_INET,AF_INET6)
* type:协议类型
* protocol:一般取0
* 返回值:成功:返回套接字文件描述符
* 失败:返回-1(错误码放在errno中)
**********************************************************/
int socket(int domain, int type, int protocol);
绑定自己的IP(和端口号)
/*********************************************************
*函数功能:绑定一个套接字
*参数:sockfd:套接字文件描述符
* addr:结构体指针,存放IP、端口、协议族等信息
* addlen:结构体大小
* 返回值:成功返回0
* 失败:返回-1(错误码放在errno中)
*********************************************************/
int bind(int sockfd, struct sockaddr* addr, int addlen)
监听客户端连接
/**********************************************************
*函数功能:监听、等待客户端连接
*参数:socket:套接字文件描述符
* backlog:可排队连接的最大连接数
* 返回值:成功:返回0
* 失败:返回-1(错误码放在errno中)
**********************************************************/
int listen(int socket, int backlog)
接受客户端的连接请求
/**********************************************************
*函数功能:TCP服务器接收客户端连接请求
*参数:sockfd:套接字问价描述符
* addr:接收客户端IP信息
* addlen:addr结构体大小
* 返回值:成功:返回交互套接字文件描述符
* 失败:返回-1(错误码放在errno中)
**********************************************************/
int accept(int sockfd, struct sockaddr* addr,int *addlen)
接收(发送)数据
/*************************************************************
*函数功能:向一个已经连接的套接字发送数据
*参数:sockfd:已连接套接字文件描述符
* buf:数据缓冲区指针,用于存放要发送的数据
* len:要发送的数据长度
* flags:调用执行方式,一般设为0
* 返回值:成功:返回发送的数据总数
* 失败:-1(错误码放入errno)
*************************************************************/
size_t send(int sockfd, const void* buf, size_t len, int flags)
/*************************************************************
*函数功能:向一个已经连接的套接字发送数据
*参数:sockfd:已连接套接字文件描述符
* buf:数据缓冲区指针,用于存放接收的数据
* len:数据缓冲区的长度
* flags:调用执行方式,一般设为0
* 返回值:成功:返回发送的数据总数
* 失败:-1(错误码放入errno)
*************************************************************/
size_t recv(int sockfd, void* buf, size_t len, int flags)
关闭套接字
int close(int socket)
2.客户端流程及接口展示
创建socket套接字文件描述符
连接服务器
/***********************************************************
*函数功能:建立与TCP服务器的连接
*参数:sockfd:套接字文件描述符
* addr:服务器端的IP和端口信息
* addlen:addr结构体长度
*返回值:成功:返回0
* 失败:返回-1(错误码放入errno)
***********************************************************/
int connect(int sockfd, struct sockaddr* addr, int addlen)
发送接收消息
关闭套接字
三、代码
1.服务器端
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int SERVER_SOCKET_INIT()
{
int sock = 0;
struct sockaddr_in server_ip;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
return -1;
}
memset(&server_ip, 0, sizeof(server_ip));
server_ip.sin_family = AF_INET;
server_ip.sin_port = htons(52013);
server_ip.sin_addr.s_addr = inet_addr("127.0.0.1");
if (bind(sock, (struct sockaddr*)&server_ip, sizeof(server_ip)) < 0) {
perror("bind");
close(sock);
return -1;
}
if (listen(sock,1024) < 0) {
perror("listen");
close(sock);
return -1;
}
printf("服务器准备就绪...\n");
printf("等待客户端连接...\n");
return sock;
}
int SERVER_METH()
{
char buffer[1024];
int sock, server_sock, len;
struct sockaddr_in client_ip;
sock = SERVER_SOCKET_INIT();
if (sock < 0) {
printf("服务器初始化失败!\n");
return -1;
}
memset(&client_ip, 0, sizeof(client_ip));
len = sizeof(client_ip);
while(1) {
server_sock = accept(sock, (struct sockaddr*)&client_ip, &len);
if (server_sock < 0) {
continue;
} else {
printf("[%s:%d]用户已连接!\n", inet_ntoa(client_ip.sin_addr), ntohs(client_ip.sin_port));
memset(buffer, 0, sizeof(buffer));
strcpy(buffer,"欢迎使用流星系统,服务器连接成功!\n");
if (send(server_sock, (char*)buffer, strlen(buffer), 0) <= 0) {
perror("send");
close(sock);
close(server_sock);
return -1;
}
memset(buffer, 0, sizeof(buffer));
if (recv(server_sock, (char*)buffer, sizeof(buffer) - 1, 0) <= 0) {
perror("recv");
close(sock);
close(server_sock);
return -1;
}
printf("[%s:%d]:%s\n", inet_ntoa(client_ip.sin_addr), ntohs(client_ip.sin_port), buffer);
printf("[%s:%d]:已断开!\n", inet_ntoa(client_ip.sin_addr), ntohs(client_ip.sin_port));
memset(buffer, 0, sizeof(buffer));
close(server_sock);
}
}
close(sock);
return 0;
}
int main()
{
int ret = SERVER_METH();
if (ret < 0) {
printf("服务器建联失败!\n");
return -1;
}
}
2.客户端代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
char buffer[1024];
int sock;
struct sockaddr_in server_ip;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
close(sock);
return -1;
}
memset(&server_ip, 0, sizeof(server_ip));
server_ip.sin_family = AF_INET;
server_ip.sin_port = htons(52013);
server_ip.sin_addr.s_addr = inet_addr("127.0.0.1");
if(connect(sock, (struct sockaddr*)&server_ip, sizeof(server_ip)) < 0) {
perror("connect");
close(sock);
return -1;
}
printf("[%s:%d]:服务器连接成功!\n",inet_ntoa(server_ip.sin_addr),ntohs(server_ip.sin_port));
memset(buffer, 0, sizeof(buffer));
if(recv(sock, (char*)buffer, sizeof(buffer) - 1, 0) < 0) {
perror("recv");
close(sock);
return -1;
}
printf("[%s:%d]:%s\n", inet_ntoa(server_ip.sin_addr), ntohs(server_ip.sin_port), buffer);
memset(buffer, 0, sizeof(buffer));
strcpy(buffer, "流星系统,你好!");
if(send(sock, (char*)buffer, strlen(buffer), 0) < 0)
{
perror("send");
close(sock);
return -1;
}
close(sock);
return 0;
}