#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
void *server(){
//1、创建socket
printf("server创建socket\n");
int serverSockfd = socket(AF_INET, SOCK_STREAM, 0);
if(serverSockfd==-1){
perror("server创建socket出现错误");
}
//结构体sockaddr和sockaddr_in都是用来处理网络通信地址的
//1、sockaddr是在<sys/socket.h>中定义的(常用于bind、connet、recvfrom、sendto函数,指明地址信息,是一种通用的套接字地址),缺陷是sa_data把目标地址和端口信息混在一起了,所以我们要使用sockaddr_in结构体
//2、sockaddr_in在<arpa/inet.h>中定义的,为了解决sockaddr缺陷,把prot和addr分开存储在两个变量中
//因为二者长度一样都是16字节,即占用的内存大小是一致的,因此可以互相转化
struct sockaddr_in sockaddrIn;
sockaddrIn.sin_family=PF_INET;
//inet_addr转换网络主机地址(点分十进制)为网络字节序二进制值,相似的函数还有inet_pton,inet_ntop(处理ipv6)
//第1种配置IP地址的方式
sockaddrIn.sin_addr.s_addr= inet_addr("127.0.0.1");
//第2种配置ip地址的方式
// struct in_addr s;
// char ip="127.0.0.1";//必须要用变量IP,传递给inet_pton参数为指针
// sockaddrIn.sin_addr.s_addr= inet_pton(AF_INET,&ip,(void *)&s);
//将主机的无符号短整形数转为网络字节顺序
//相似的函数还有htonl(host to network long)、ntohl(network to host long)、ntohs(network to host short)
sockaddrIn.sin_port= htons(10000);
//2、绑定端口
printf("server绑定端口\n");
if (bind(serverSockfd, (struct sockaddr *)&sockaddrIn, sizeof(sockaddrIn))==-1){
perror("server绑定端口出现错误");
}
//3、监听
printf("server监听端口\n");
if (listen(serverSockfd,1)==-1){
perror("server监听出现错误");
}
//4、接收数据
printf("server接收client连接状态\n");
struct sockaddr sockaddr;
int len = sizeof(struct sockaddr);//必须得用变量len,不能直接使用(int *)sizeof(struct sockaddr)
int clientConnectfd = accept(serverSockfd, (struct sockaddr*)&sockaddr, &len);
if(clientConnectfd==-1){
perror("server接收client连接错误");
}
printf("server已接收到client连接\n");
//5、读取数据
char buffer[100];
ssize_t i = read(clientConnectfd, &buffer, 100);
printf("server读取到消息长度:%d\n",i);
printf("server读取到消息内容:%s\n",buffer);
//6、回应客户端
printf("server回复client端数据\n");
char bufferClient[100]="I am server";
if(write(clientConnectfd,bufferClient,100)==-1){
perror("server回复client端数据时错误");
}
//7、关闭客户端socket
if(close(clientConnectfd)==-1){
perror("关闭client连接错误");
}
if(close(serverSockfd)==-1){
perror("关闭server socket连接错误");
}
printf("server结束\n");
}
void *client(){
//1、创建socket
printf("client创建socket\n");
int clientSockfd = socket(AF_INET, SOCK_STREAM, 0);
if(clientSockfd==-1){
perror("client创建socket出现错误");
}
//2、连接server端
printf("client连接server端\n");
//使用第2种配置ip地址的方式
struct sockaddr_in sockaddrIn;
sockaddrIn.sin_family=PF_INET;
struct in_addr s;
char ip="127.0.0.1";
sockaddrIn.sin_addr.s_addr= inet_pton(AF_INET,&ip,(void *)&s);
sockaddrIn.sin_port= htons(10000);
if(connect(clientSockfd, (struct sockaddr*)&sockaddrIn, sizeof(struct sockaddr))==-1){
perror("client连接server错误");
}
//3、发送数据
printf("client发送server端数据\n");
char bufferSend[100]="I am client";
if(write(clientSockfd,bufferSend,100)==-1){
perror("client发送server数据时错误");
}
//4、接收客户端返回的数据
printf("client接收server端回应数据\n");
char bufferRecv[100];
ssize_t i = recv(clientSockfd, bufferRecv, 100, 0);
printf("client读取到server回应的消息长度:%d\n",i);
printf("client读取到server回应的消息内容:%s\n",bufferRecv);
//5、关闭
if(close(clientSockfd)==-1){
perror("关闭client socket连接错误");
}
printf("client结束\n");
}
int main() {
printf("Hello, World!\n");
pthread_t pthread_t,pthread_t2;
if(pthread_create(&pthread_t, NULL, server, NULL) == -1){
perror("创建线程1失败");
}
if(sleep(1)!=0){
perror("休眠失败");
}
if(pthread_create(&pthread_t2, NULL, client, NULL) == -1){
perror("创建线程2失败");
}
if(sleep(60)!=0){
perror("休眠失败");
}
//销毁资源
if(pthread_detach(&pthread_t)==-1){
perror("销毁线程1失败");
}
if(pthread_detach(&pthread_t2)==-1){
perror("销毁线程2失败");
}
return 0;
}
执行结果:
Hello, World!
server创建socket
server绑定端口
server监听端口
server接收client连接状态
client创建socket
client连接server端
client发送server端数据
server已接收到client连接
client接收server端回应数据
server读取到消息长度:100
server读取到消息内容:I am client
server回复client端数据
server结束
client读取到server回应的消息长度:100
client读取到server回应的消息内容:I am server
client结束