基本:
客户端:
#include"tt.h"
int main()
{
//1.建立通信套接字
int fd=socket(AF_INET,SOCK_STREAM,0);
if(fd==-1)
{
perror("fail to socket");
exit(1);
}
//2.连接服务器
struct sockaddr_in addr;
bzero(&addr,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_port=htons(6000);//网络字节序的端口号,表示与服务器该端口通信
inet_pton(AF_INET,my_ip,(void *)&addr.sin_addr.s_addr);//这里的IP地址为服务器的IP地址
//客户端去连接服务器,不需要知道自己的IP和端口,只需要知道服务器的就行
int ret=connect(fd,(struct sockaddr*)&addr,sizeof(addr));
if(ret==-1)
{
perror("fail to connect");
exit(1);
}
printf("通信已连接");
//3.通信
int num=1;
int len;
while(1)
{
//发送数据
char buf[1024];
sprintf(buf,"你好,服务器,第%d次和你通信",num++);
send(fd,buf,strlen(buf)+1,0);
//接受数据
bzero(buf,sizeof(buf));
len=recv(fd,buf,sizeof(buf),0);
{
if(len>0)
{
printf("服务器:%s\n",buf);
}
else if(len==0)
{
printf("和服务器断开");
break;
}
else
{
perror("fail to recv");
break;
}
/* if(!strncasecmp(buf,"quit",strlen("quit")))
{
printf("client is exiting!\n");
exit(1);
}*/
sleep(1);
}
}
//4.关闭套接字
close(fd);
}
服务器:
#include"tt.h"
int main()
{
//1.创建监听套接字
int fd=socket(AF_INET,SOCK_STREAM,0);//AF_INET表示ipv4,通信类型tcp为传输流协议即数据报套接字,默认0表示TCP
if(fd==-1)
{
perror("fail to socket");
exit(1);
}
//2.绑定我们本地的IP地址和端口号
struct sockaddr_in addr;//bend用的结构体
addr.sin_family=AF_INET;//表示协议族,基于ipv4
addr.sin_port=htons(6000);//端口号,5000以上就行,由本地小端转为网络传输用的大端,端口号为16位,所以用s
inet_pton(AF_INET,my_ip,(void *)&addr.sin_addr.s_addr);//将转换后的IP地址放到sin_addr下
int ret=bind(fd,(struct sockaddr *)&addr,sizeof(addr));
if(ret==-1)
{
perror("fail to bink");
exit(1);
}
//3.设置监听
ret=listen(fd,128);//同一时刻一次监听多少个,最大值为128,不代表最终只能连接这么多
//listen的作用是把一个未连接的套接字转换为被动套接字,指示内核应该接受指向该套接字的连接请求。使套接字从close状态转换到listen状态
if(ret==-1)
{
perror("fail to listen");
exit(1);
}
//4.阻塞等待,连接的到达,连接成功后返回通信用的套接字
struct sockaddr_in caddr;
int caddrlen=sizeof(caddr);
int newfd =accept(fd,(struct sockaddr *)&caddr,&caddrlen);//第二个参数用来保存客户端套接字对应的“地方”(包括客户端IP和端口信息等),第三个参数是“地方”的占地大小,返回值对应客户端套接字标识,失败返回-1
if(newfd==-1)
{
perror("fail to accept");
exit(1);
}
//5.开始通行
char buf[1024];//用来存储接收到的数据
while(1)
{
//读就是receive或read,写就是send或write
bzero(buf,sizeof(buf));//清0
//memset也行
ret=read(newfd,buf,1024);//(1)通信套接字(2)缓冲区(3)缓冲区长度 --read返回读取的长度,0表示断开连接,负数表示读取失败
//读:read/recv 写:write/send
char ip[30]={'0'};
if(ret>0)
{
printf("客户端 %s:%d:%s\n",inet_ntop(AF_INET,&caddr.sin_addr.s_addr,ip,sizeof(ip)),ntohs(caddr.sin_port),buf);
write(newfd,buf,ret);
}
else if(ret==0)
{
printf("连接已断开\n");
break;
}
else
{
perror("fail to read");
break;
}
}
//6.关闭套接字
close(fd);
close(newfd);
return 0;
}
多线程:
#include"tt.h"
#include<pthread.h>
struct pp
{
struct sockaddr_in caddr;
int newfd;
};
void* TX(void *arg)
{
char buf[1024];
struct pp ADD=*(struct pp*)arg;
while(1)
{
bzero(buf,sizeof(buf));//清0
int ret=read(ADD.newfd,buf,1024);//(1)通信套接字(2)缓冲区(3)缓冲区长度 --read返回读取的长度,0表示断开连接,负数表示读取失败
char ip[30]={'0'};
if(ret>0)
{
printf("客户端 %s:%d:%s\n",inet_ntop(AF_INET,&ADD.caddr.sin_addr.s_addr,ip,sizeof(ip)),ntohs(ADD.caddr.sin_port),buf);
write(ADD.newfd,buf,ret);
}
else if(ret==0)
{
printf("连接已断开\n");
break;
}
else
{
perror("fail to read");
break;
}
}
close(ADD.newfd);
pthread_exit(NULL);
}
int main()
{
//1.创建监听套接字
int fd=socket(AF_INET,SOCK_STREAM,0);//AF_INET表示ipv4,通信类型tcp为传输流协议即数据报套接字,默认0表示TCP
if(fd==-1)
{
perror("fail to socket");
exit(1);
}
//2.绑定我们本地的IP地址和端口号
struct sockaddr_in addr;//bend用的结构体
addr.sin_family=AF_INET;//表示协议族,基于ipv4
addr.sin_port=htons(6000);//端口号,5000以上就行,由本地小端转为网络传输用的大端,端口号为16位,所以用s
inet_pton(AF_INET,my_ip,(void *)&addr.sin_addr.s_addr);//将转换后的IP地址放到sin_addr下
int ret=bind(fd,(struct sockaddr *)&addr,sizeof(addr));
if(ret==-1)
{
perror("fail to bink");
exit(1);
}
//3.设置监听
ret=listen(fd,128);//同一时刻一次监听多少个,最大值为128,不代表最终只能连接这么多
//listen的作用是把一个未连接的套接字转换为被动套接字,指示内核应该接受指向该套接字的连接请求。使套接字从close状态转换到listen状态
if(ret==-1)
{
perror("fail to listen");
exit(1);
}
//4.阻塞等待,连接的到达,连接成功后返回通信用的套接字
struct sockaddr_in caddr;
int caddrlen=sizeof(caddr);
pthread_t pid;
struct pp ADD;
while(1)
{
int newfd =accept(fd,(struct sockaddr *)&caddr,&caddrlen);
if(newfd==-1)
{
perror("fail to accept");
exit(1);
}
ADD.caddr=caddr;
ADD.newfd=newfd;
pthread_create(&pid,NULL,TX,&ADD);
pthread_detach(pid);//将线程pid设置为detach状态,就不会产生僵尸线程
}
//6.关闭套接字
close(fd);
return 0;
}
多进程:
#include"tt.h"
#include<signal.h>
int main()
{
signal(SIGCHLD,SIG_IGN);//忽略子进程退出信号,避免产生僵尸进程
//1.创建监听套接字
int fd=socket(AF_INET,SOCK_STREAM,0);//AF_INET表示ipv4,通信类型tcp为传输流协议即数据报套接字,默认0表示TCP
if(fd==-1)
{
perror("fail to socket");
exit(1);
}
//2.绑定我们本地的IP地址和端口号
struct sockaddr_in addr;//bend用的结构体
addr.sin_family=AF_INET;//表示协议族,基于ipv4
addr.sin_port=htons(6000);//端口号,5000以上就行,由本地小端转为网络传输用的大端,端口号为16位,所以用s
inet_pton(AF_INET,my_ip,(void *)&addr.sin_addr.s_addr);//将转换后的IP地址放到sin_addr下
int ret=bind(fd,(struct sockaddr *)&addr,sizeof(addr));
if(ret==-1)
{
perror("fail to bink");
exit(1);
}
//3.设置监听
ret=listen(fd,128);//同一时刻一次监听多少个,最大值为128,不代表最终只能连接这么多
//listen的作用是把一个未连接的套接字转换为被动套接字,指示内核应该接受指向该套接字的连接请求。使套接字从close状态转换到listen状态
if(ret==-1)
{
perror("fail to listen");
exit(1);
}
//4.阻塞等待,连接的到达,连接成功后返回通信用的套接字
struct sockaddr_in caddr;
int caddrlen=sizeof(caddr);
while(1)
{
int newfd =accept(fd,(struct sockaddr *)&caddr,&caddrlen);
if(newfd==-1)
{
perror("fail to accept");
exit(1);
}
pid_t pid=fork();
if(pid<0)
{
perror("fail to fork");
exit(1);
}
if(pid==0)
{
char buf[1024];
while(1)
{
bzero(buf,sizeof(buf));
ret=read(newfd,buf,1024);//(1)通信套接字(2)缓冲区(3)缓冲区长度 --read返回读取的长度,0表示断开连接,负数表示读取失败
//读:read/recv 写:write/send
char ip[30]={0};
if(ret>0)
{
printf("客户端 %s:%d:%s\n",inet_ntop(AF_INET,&caddr.sin_addr.s_addr,ip,sizeof(ip)),ntohs(caddr.sin_port),buf);
write(newfd,buf,ret);
}
else if(ret==0)
{
printf("连接已断开\n");
break;
}
else
{
perror("fail to read");
break;
}
}
close(newfd);
}
}
//6.关闭套接字
close(fd);
return 0;
}