#include
#include
#include
#include
#include
#include
#include
#include
#include
void *read_msg(void *arg);
void *read_msg(void *arg)
{
int fbap=*((int*)arg);
char msg[1024];
while (1)
{
memset(msg, 0, sizeof(msg));
read(fbap,msg,sizeof(msg));
printf("客户端收到消息:%s\n",msg);
}
}
int main(int argc, char const *argv[])
{
// 1、创建socket
int fb = socket(AF_INET, SOCK_STREAM, 0);
if (fb < 0)
{
perror("socket");
return 0;
}
struct sockaddr_in addr; // 定义结构体
addr.sin_family = AF_INET; // 设置为IPV4
addr.sin_port = htons(8881); // 设置端口号为8080 htons():将本地网络字序改为网络传输统一的大端存储的字序
// ntohs() 将网络字序转化为本地主机字序
addr.sin_addr.s_addr = inet_addr("192.168.1.2"); // 设置网络IP inet_addr():将字符串转化为整型地址
// 2、绑定socket
if (bind(fb, (struct sockaddr *)&addr, sizeof(addr)))
{
perror("bind");
}
// 3、设置监听,,模式
if (listen(fb, 3))
{
perror("listen");
}
// 4、接收请求
struct sockaddr_in cli_addr;
socklen_t len = sizeof(cli_addr);
int fbap = accept(fb, (struct sockaddr *)(&cli_addr), &len);
if (fbap < 0)
{
perror("accept");
}
printf("fbap=%d\n", fbap);
printf("ntohs(cli_addr.sin_port)=%d\n", ntohs(cli_addr.sin_port));
printf(" inet_ntoa(cli_addr.sin_addr)=%s\n", inet_ntoa(cli_addr.sin_addr));
pthread_t id;
pthread_create(&id, NULL, read_msg, &fbap);
char msg[1024];
while (1)
{
memset(msg, 0, sizeof(msg));
printf("请输入客户端消息\n");
scanf("%s",msg);
if (strcmp(msg,"exit")==0)
{
break;
}
write(fbap,msg,strlen(msg));
}
close(fb);
close(fbap);
return 0;
}
1、创建TCPsocket
2,绑定服务器socket
3、设置监听模式
4、接收请求
5,通信(read/write)
6、关闭通信
每接到一个请求就会分配一个文件描述符,然后就当文件I/O即可。所以可以实现多端同时通信。
NAME
socket - create an endpoint for communication
SYNOPSIS
#include
#include
申请一个套接字;
int domain :IP协议 IPV4——AF_INET IPv4 Internet protocols
IPV6——AF_INET6 IPv6 Internet protocols
int type :通信协议 UDP SOCK_DGRAM
TCP SOCK_STREAM
protocol :说明该套接字使用的特定协议,如果调用者不希望特别指定使用的协议,则置为0,使用默认的连接模式。根据这三个参数建立一个套接字,并将相应的资源分配给它,同时返回一个整型套接字号。因此,socket()系统调用实际上指定了相关五元组中的“协议”这一元。
成功:返回一个socketfb,其本质类似于一个文件描述符,相当于打开一个文件一样,是一个大于2的整数。
失败:返回-1;
绑定服务器套接字以及IP信息、端口等数据;
NAME
bind - bind a name to a socket
SYNOPSIS
#include
#include
int sockfb :服务端对象的fb
const struct sockaddr *addr: 服务器地址
socklen_t addrlen 服务器地址长度
//------------------------------------------------------------------
// 服务器地址原始结构体
// struct sockaddr
// {
// sa_family_t sa_family; 无符号短整型 16位 表示IP协议
// char sa_data[14]; 数据ip地址 + 端口号
// };
//------------------------------------------------------------------
// 服务器结地址结构体改良版
// struct sockaddr_in
// {
// sa_family_t sin_family; 无符号短整型 16位 表示IP协议 /* address family: AF_INET */
// in_port_t sin_port; 端口号 16位 /* port in network byte order */
// struct in_addr sin_addr; 32位 IP地址 /* internet address */
// };
//-------------------------------------------------------------------
// struct in_addr
// {
// uint32_t s_addr; /* address in network byte order */
// };
//------------------------------------------------------------------
成功返回:0 失败返回:-1;
NAME
listen - listen for connections on a socket
SYNOPSIS
#include
#include
设置监听模式
sockfd:为创建socket返回的文件描述符。
backlog:为建立好连接处于ESTABLISHED状态的队列的长度。
成功:返回0; 失败:返回-1;
RETURN VALUE
On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
NAME
accept, accept4 - accept a connection on a socket
SYNOPSIS
#include
#include
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
接收客户端连接;
int sockfb :服务端对象的fb
struct sockaddr *addr :用于接收客户端连接套接字的IP端口数据结构体
socklen_t addrlen :客户端地址长度
成功:返回客户端连接的sockfb; 失败返回:-1;
RETURN VALUE
On success, these system calls return a nonnegative integer that is a file descriptor for the accepted socket. On error, -1 is returned, and errno is set appropriately.
5、read/write
6、close