知识点 socket是一种编程接口 socket是一中特殊文件描述符

五要素 协议(接头暗号) 本地地址 本地端口 远程地址 远程端口 ** TCP 三次握手四次挥手**

接口转换操作

  1. 字节序转换

点分十进制数串转网络字节序长整形

int inet_aton(const char *string, struct in_addr*addr)

2.IP地址转换操作 结构体

  • 套接字地址结构
struct sockaddr {
    unsigned short sa_family; // 套接字地址簇类型,为AF_INET
    char sa_data[14];         // 套接字地址数据(14位的协议地址)
};
  • IPV4套接字地址结构
struct sockaddr_in{
    short sin_family;         // 套接字地址簇类型,为AF_INET
    unsigned short sin_port;  // 端口号,网络字节序
    struct in_addr sin_addr;  // IP地址,网络字节序
    unsigned char sin_zero[8];// 填充字节
};
  • IPV4地址结构
struct in_addr {
    in_addr_t s_addr;
};
  • IPV4地址类型
typedef unsigned int in_addr_t;

socket操作

  1. 创建
  int socket(int domain, int type, int protocol)

2.关闭

	int close(int sockfd)
int shutdown(int sockfd,int howto)

3.属性 设置

int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen)

获取

int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen)

4.绑定

int bind(int socket, const struct sockaddr* address, socklen_t address_len)

5.监听

int listen(int sockfd, int backlog)

6.连接

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

7.接收

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)

8.接受(分客户端和服务端)

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)

如果不需要获取客户端套接字地址,后面两个参数设置为NULL

9.发送(分客户端和服务端)

ssize_t write(int fd, const void *buf, size_t len);

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

10.接收

ssize_t read(int fd, void *buf, size_t len);

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen)

实践 1.特殊地址设置 2.原则 客户端/发送端 必须指定连接/发送的IP(广播地址、回环地址或者某个具体地址)。 必须指定连接/发送的port。 服务器/接受端 IP指定为通配地址、回环地址或者某个具体地址。 必须指定绑定监听/接受的port。 netstat 查看网络连接状态、socket端口打开状态

代码实现大纲图:

功能: 实现简单的服务端与服务器的交互 服务器端

#include<iostream>
#include<arpa/inet.h>
#nclude<unistd.h>
#include<strings.h>
using namespace std;


void show_connect(int fd){
		struct sockaddr_in  local_addr;
		socklen_t local_addr_len=sizeof(local_addr);
		bzero(&local_addr,local_addr_len);
		getsockname(fd,(struct sockaddr*)&local_addr,&local_addr_len);
			cout<<"local"<<inet_ntoa(local_addr.sin_addr)<<":"<<ntohs(local_addr.sin_port)<<endl;
			
			struct sockaddr_in remote_addr;
			socklen_t remote_addr_len=sizeof(remote_addr);
			bzero(&remote_addr,remote_addr_len);
			getpeername(fd,(struct sockaddr*)&remote_addr,&remote_addr_len);
			cout<<"remote"<<inet_ntoa(remote_addr.sin_addr)<<":"<<ntohs(remote_addr.sin_port)<<endl;
}

void* read_msg(void* fd){
		int connfd=*(int*)fd;
		while(true){
		  //读数据
			char buffer[1024]={0};
			int len=recv(connfd,buffer,sizeof(buffer),0);
			if(len==0){
				cout<<"client exit"<<endl;
				break;
			}else{
				cout<<"client:"<<buffer<<endl;
			}
		}
}
void* write_msg(void* fd){
		 int connfd=*(int*)fd;
		 while(true){
		 //写数据
		 string message;
		 getline(cin,message);
		 send(connfd,mesaage.c_str(),message.szie()+1,0);
		 }
}
//./server ip port
int  main(int argc,char* argv[]){
		if(argc!=3){
			cout<<"usage:"<<argv[0]<<"Ip port"<<endl;
			return 1;
		}
		
		//1.监听套接字
		int listenfd=socket(AF_INET,SOCK_STREAM,0);
		if(listenfd==-1){
		 cout<<"listen socket error"<<endl;
		 return 1;
		}
		
		//2.绑定
		
		struct sockaddr_in local_addr;
		local_addr.sin_family=AF_INET;//协议
		local_addr.sin_addr.s_addr=inet_addr(argv[1]);//IP地址
		local_addr.sin_port=htons(atoi(argv[2]));//端口号
		
		
		if(-1==bind(listenfd,(struct sockaddr*)&local_addr,sizeof(local_addr))){
		cout<<"bind error"<<endl;
		return 1;
		}else{
		  cout<<"bind success"<<endl;
		}
		
		//3.监听设置
		if(listen(listenfd,10)==-1){
			cout<<"listen error"<<endl;
			return 1;
		}else{
		   cout<<"listen success"<<endl;
		}
		//4.等待接收
		struct sockaddr_in remote_addr;
		bzero(&remote_addr,sizeof(remote_addr));
		socklen_t remote_addr_len=sizeof(remote_addr);
		int connfd=accept(listenfd,(struct sockaddr*)&remote_addr,&remote_addr_len);
		if(connfd==-1){
		   cout<<"accept error"<<endl;
			 return 1;
		}else{
		  cout<<"accept success"<<endl;
			cout<<inet_ntoa(remote_addr.sin_addr)<<":"<<ntohs(remote_addr.sin_port)<<endl;
			show_connfd(connfd);
		}
		
		pthread_t tids[2];
		pthread_create(tids,NULL,write_msg,&connfd);
		pthread_create(tids+1,NULL,read_msg,&connfd);
		
		
		for(auto tid:tids){
		 pthread_join(tid,NULL);
		}
		
		
		//关闭套接字
		close(connfd);
		close(listenfd);		
}

客户端

#include<iostream>
#include<arpa/inet.h>
#nclude<unistd.h>
#include<strings.h>
using namespace std;


void show_connect(int fd){
//获取本地址和端口
		struct sockaddr_in  local_addr;
		socklen_t local_addr_len=sizeof(local_addr);
		bzero(&local_addr,local_addr_len);
		getsockname(fd,(struct sockaddr*)&local_addr,&local_addr_len);
			cout<<"local"<<inet_ntoa(local_addr.sin_addr)<<":"<<ntohs(local_addr.sin_port)<<endl;
		//获取远程地址和端口
			struct sockaddr_in remote_addr;
			socklen_t remote_addr_len=sizeof(remote_addr);
			bzero(&remote_addr,remote_addr_len);
			getpeername(fd,(struct sockaddr*)&remote_addr,&remote_addr_len);
			cout<<"remote"<<inet_ntoa(remote_addr.sin_addr)<<":"<<ntohs(remote_addr.sin_port)<<endl;
}

void* read_msg(void* fd){
		int connfd=*(int*)fd;
		while(true){
		  //读数据
			char buffer[1024]={0};
			int len=read(connfd,buffer,sizeof(buffer));
			if(len==0){
				cout<<"server exit"<<endl;
				break;
			}else{
				cout<<"server:"<<buffer<<endl;
			}
		}
}
void* write_msg(void* fd){
		 int connfd=*(int*)fd;
		 while(true){
		 //发送消息
		 string message;
		 getline(cin,message);
		 write(connfd,mesaage.c_str(),message.szie()+1);
		 }
}
//./client ip port
int  main(int argc,char* argv[]){
		if(argc!=3){
			cout<<"usage:"<<argv[0]<<"Ip port"<<endl;
			return 1;
		}
		
		//1.创建套接字
		int connfd=socket(AF_INET,SOCK_STREAM,0);
		if(connfd==-1){
		 cout<<" socket error"<<endl;
		 return 1;
		}
		
		//2连接服务器
		
		struct sockaddr_in remote_addr;
		remote_addr.sin_family=AF_INET;//协议
		remote_addr.sin_addr.s_addr=inet_addr(argv[1]);//IP地址
		remote_addr.sin_port=htons(atoi(argv[2]));//端口号
		
		
		if(-1==connect(connfd,(struct sockaddr*)&remote_addr,sizeof(remote_addr))){
		cout<<"connect error"<<endl;
		return 1;
		}else{
		  cout<<"connect success"<<endl;
			show_connect(connfd);
		}
		

		
		pthread_t tids[2];
		pthread_create(tids,NULL,write_msg,&connfd);
		pthread_create(tids+1,NULL,read_msg,&connfd);
		
		
		for(auto tid:tids){
		 pthread_join(tid,NULL);
		}
		
		
		//关闭套接字
		close(connfd);
	  return 0;
}

基于tcp/ip实现
功能:服务端实现发送信息到所有客户端 客户端传消息给服务端 让服务端帮转消息给除自己的所有客户端

服务器端

#include<iostream>
#include<arpa/inet.h>
#nclude<unistd.h>
#include<strings.h>
using namespace std;



void show_connect(int fd){
		struct sockaddr_in  local_addr;
		socklen_t local_addr_len=sizeof(local_addr);
		bzero(&local_addr,local_addr_len);
		getsockname(fd,(struct sockaddr*)&local_addr,&local_addr_len);
			cout<<"local"<<inet_ntoa(local_addr.sin_addr)<<":"<<ntohs(local_addr.sin_port)<<endl;
			
			struct sockaddr_in remote_addr;
			socklen_t remote_addr_len=sizeof(remote_addr);
			bzero(&remote_addr,remote_addr_len);
			getpeername(fd,(struct sockaddr*)&remote_addr,&remote_addr_len);
			cout<<"remote"<<inet_ntoa(remote_addr.sin_addr)<<":"<<ntohs(remote_addr.sin_port)<<endl;
}

./server ip port
int  main(int argc,char* argv[]){
		if(argc!=3){
			cout<<"usage:"<<argv[0]<<"Ip port name"<<endl;
			return 1;
		}
		
		//1.监听套接字
		int listenfd=socket(AF_INET,SOCK_STREAM,0);
		if(listenfd==-1){
		 cout<<"listen socket error"<<endl;
		 return 1;
		}
		//设置端口重复利用
		 int  flag=1; setsockopt(listenfd,SQL_SOCKET,SO_REUSEADDR,&flag,sizeof(flag));
		
		//2.绑定
		
		struct sockaddr_in local_addr;
		local_addr.sin_family=AF_INET;//协议
		local_addr.sin_addr.s_addr=inet_addr(argv[1]);//IP地址
		local_addr.sin_port=htons(atoi(argv[2]));//端口号
		
		
		if(-1==bind(listenfd,(struct sockaddr*)&local_addr,sizeof(local_addr))){
		cout<<"bind error"<<endl;
		return 1;
		}else{
		  cout<<"bind success"<<endl;
		}
		
		//3.监听设置
		if(listen(listenfd,10)==-1){
			cout<<"listen error"<<endl;
			return 1;
		}else{
		   cout<<"listen success"<<endl;
		}
		
		vector<int> fds;
		thread([&fds]{
		  while(true){
			  string message;
				getline(cin,message);
				message="广告"+message;
				for(auto fd:fds){
				  write(fd,message.c_str(),message.size(0+1);
				}
			}
		}).detach();
		
		//4.等待接收
		while(true){
		struct sockaddr_in remote_addr;
		bzero(&remote_addr,sizeof(remote_addr));
		socklen_t remote_addr_len=sizeof(remote_addr);
		int connfd=accept(listenfd,(struct sockaddr*)&remote_addr,&remote_addr_len);
		if(connfd==-1){
		   cout<<"accept error"<<endl;
			 return 1;
		}else{
		  cout<<"accept success"<<endl;
			cout<<inet_ntoa(remote_addr.sin_addr)<<":"<<ntohs(remote_addr.sin_port)<<endl;
			show_connfd(connfd);
			fds.push_back(connfd);
		}
		
		thread([connfd,&fds]{
		  while(true){
			  char buffer[1024]={0};
				int n=read(connfd,buffer,1024);//读取客户端发过来的消息
				if(n==0){
				 break;
				}else{
				  for(auto fd:fds){  //发送消息给除了自己的所有客户端
					  if(fd==connfd) continue;
						write(fd,buffer,1024);
					}
				}
			}
		
		}).detach();
		
		
		close(listenfd);		
}

客户端

#include<iostream>
#include<arpa/inet.h>
#nclude<unistd.h>
#include<strings.h>
using namespace std;

string name;

void show_connect(int fd){
//获取本地址和端口
		struct sockaddr_in  local_addr;
		socklen_t local_addr_len=sizeof(local_addr);
		bzero(&local_addr,local_addr_len);
		getsockname(fd,(struct sockaddr*)&local_addr,&local_addr_len);
			cout<<"local"<<inet_ntoa(local_addr.sin_addr)<<":"<<ntohs(local_addr.sin_port)<<endl;
		//获取远程地址和端口
			struct sockaddr_in remote_addr;
			socklen_t remote_addr_len=sizeof(remote_addr);
			bzero(&remote_addr,remote_addr_len);
			getpeername(fd,(struct sockaddr*)&remote_addr,&remote_addr_len);
			cout<<"remote"<<inet_ntoa(remote_addr.sin_addr)<<":"<<ntohs(remote_addr.sin_port)<<endl;
}



//./client ip port
int  main(int argc,char* argv[]){
		if(argc!=4){
			cout<<"usage:"<<argv[0]<<"Ip port name"<<endl;
			return 1;
		}
		name=argv[3];
		//1.创建套接字
		int connfd=socket(AF_INET,SOCK_STREAM,0);
		if(connfd==-1){
		 cout<<" socket error"<<endl;
		 return 1;
		}
		
		//2连接服务器
		
		struct sockaddr_in remote_addr;
		remote_addr.sin_family=AF_INET;//协议
		remote_addr.sin_addr.s_addr=inet_addr(argv[1]);//IP地址
		remote_addr.sin_port=htons(atoi(argv[2]));//端口号
		
		
		if(-1==connect(connfd,(struct sockaddr*)&remote_addr,sizeof(remote_addr))){
		cout<<"connect error"<<endl;
		return 1;
		}else{
		  cout<<"connect success"<<endl;
			show_connect(connfd);
		}
		
thread([=]{
  while(true){
	  string message;
		 getline(cin,message);
		 message =name+":"+message;
		 write(connfd,mesaage.c_str(),message.szie()+1);
	}
}).detach();


thread([=]{
 while(true){
 	char buffer[1024]={0};
			int len=read(connfd,buffer,sizeof(buffer));
			if(len==0){
				cout<<"server exit"<<endl;
				break;
			}else{
				cout<<"server:"<<buffer<<endl;
			}
 }
}).detach();
		
		//关闭套接字
		close(connfd);
	  return 0;
}