参考
https://www.cnblogs.com/diligenceday/p/6241021.html
https://blog.csdn.net/baidu_36649389/article/details/79081770
http://www.cnblogs.com/wangcq/p/3520400.html
socket是网络进程的PID,由运行进程的计算机的IP地址和进程使用的端口组成。
异步状态下connect不阻塞,直接返回-1,connect返回-1是对的
然后通过select进行判断是否连接上
同步状态下connect阻塞,系统莫认时间75秒后,返回成功或失败
TCP编程的流程
服务器端
//
// main.cpp
// Server
//
// Created by 蓝猫 on 2018/12/13.
// Copyright © 2018年 蓝猫. All rights reserved.
//
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#define PORT 25555
#define BACK_LOG 20 //队列允许请求数
#define BUF_SIZE 256 // 缓冲区大小
#define IP "192.168.1.5"
using std::cout;
using std::endl;
int main(int argc, const char * argv[])
{
int ret;
time_t tt;
struct tm *ttm;
char buf[BUF_SIZE];
pid_t pid;//定义进程描述符
int sockfd; //
int clientfd;
struct sockaddr_in host_addr;
struct sockaddr_in client_addr;
int length=sizeof(clientfd);
sockfd=socket(AF_INET, SOCK_STREAM, 0);
if(sockfd==-1)
{
cout<<"创建socket失败"<<endl;
exit(1);
}
bzero(&host_addr, sizeof(host_addr));
host_addr.sin_family=AF_INET;//TCP/IP协议
host_addr.sin_port=htons(PORT);//设置端口
host_addr.sin_addr.s_addr=INADDR_ANY;//本地ip
ret=bind(sockfd, (const struct sockaddr *)&host_addr, sizeof(host_addr));//绑定ip和端口
if(ret==-1)
{
cout<<"bind失败"<<endl;
exit(1);
}
else
{
cout<<"bind成功"<<endl;
}
//监听网络端口
ret=listen(sockfd, BACK_LOG);
if(ret==-1)
{
cout<<"监听失败"<<endl;
exit(1);
}
while (1)
{
/*
倾听队列之后 accept可以从倾听套接字的完成队列里面接受一个连接,如果队列是空,进程进入睡眠状态。
accept调用成功
函数返回值是一个新的标识符,标识接收的连接
第二个参数描述客户机地址 第三个描述客户机地址长度
*/
//clientfd=accept(sockfd, (struct sockaddr *)&client_addr, &length);//接收连接请求
//clientfd=accept(sockfd, (struct sockaddr *)&client_addr,&length);
clientfd = accept(sockfd, (struct sockaddr*)&client_addr, (socklen_t *)&length);
if(clientfd==-1)
{
cout<<"接收失败"<<endl;
exit(1);
}
pid=fork();
if(pid==0)
{
while (1)
{
bzero(buf, sizeof(buf));
tt=time(NULL);
ttm=localtime(&tt);//获取当前时间参数
strcpy(buf, asctime(ttm));// 将时间拷贝到缓冲区
send(clientfd, buf, strlen(buf), 0);//发送数据
sleep(2);
}
close(clientfd);
}
else if(pid>0)
{
close(clientfd);//父进程关闭套接字 ,准备下一个客户端连接
}
}
return 0;
}
客户端
//
// main.cpp
// Client
//
// Created by 蓝猫 on 2018/12/13.
// Copyright © 2018年 蓝猫. All rights reserved.
//
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#define PORT 25555
#define BACK_LOG 20 //队列允许请求数
#define BUF_SIZE 256 // 缓冲区大小
#define IP "192.168.1.5"
using std::cout;
using std::endl;
int main(int argc, const char * argv[])
{
int ret;
char buf[BUF_SIZE];
int sockfd;//套接字描述符
struct sockaddr_in serv_addr;// 服务器端的端口号和ip
sockfd=socket(AF_INET, SOCK_STREAM, 0);
if(sockfd==-1)
{
cout<<" socket创建失败"<<endl;
return 2;
}
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(PORT);
inet_aton(IP, (struct in_addr *)&serv_addr.sin_addr.s_addr);
//serv_addr.sin_addr.s_addr=INADDR_ANY;
cout<<"here1"<<endl;
ret=connect(sockfd, (const struct sockaddr *)&serv_addr, sizeof(serv_addr));
cout<<"here2"<<endl;
if(ret==-1)
{
cout<<"connect失败"<<endl;
return 3;
}
else
{
cout<<"connect success"<<endl;
}
while (1)
{
bzero(buf, sizeof(buf));
recv(sockfd, buf, sizeof(buf), 0);
printf("接收到数据:%s",buf);
sleep(1);
}
close(sockfd);
return 0;
}
用多线程实现客户端和服务器端同时运行
//
// main.cpp
// 多线程实现tcp c/s交互
//
// Created by 蓝猫 on 2018/12/14.
// Copyright © 2018年 蓝猫. All rights reserved.
//
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pthread.h>
#define PORT 25554
#define BACK_LOG 20 //队列允许请求数
#define BUF_SIZE 256 // 缓冲区大小
#define IP "192.168.1.5"
using std::cout;
using std::endl;
int server()
{
int ret;
time_t tt;
struct tm *ttm;
char buf[BUF_SIZE];
pid_t pid;//定义进程描述符
int sockfd; //
int clientfd;
struct sockaddr_in host_addr;
struct sockaddr_in client_addr;
int length=sizeof(clientfd);
sockfd=socket(AF_INET, SOCK_STREAM, 0);
if(sockfd==-1)
{
cout<<"服务器:创建socket失败"<<endl;
exit(1);
}
bzero(&host_addr, sizeof(host_addr));
host_addr.sin_family=AF_INET;//TCP/IP协议
host_addr.sin_port=htons(PORT);//设置端口
host_addr.sin_addr.s_addr=INADDR_ANY;//本地ip
ret=bind(sockfd, (const struct sockaddr *)&host_addr, sizeof(host_addr));//绑定ip和端口
if(ret==-1)
{
cout<<"服务器:bind失败"<<endl;
exit(1);
}
else
{
cout<<"服务器:bind成功"<<endl;
}
//监听网络端口
cout<<"服务器:开始监听"<<endl;
ret=listen(sockfd, BACK_LOG);
if(ret==-1)
{
cout<<"服务器:监听失败"<<endl;
exit(1);
}
while (1)
{
/*
倾听队列之后 accept可以从倾听套接字的完成队列里面接受一个连接,如果队列是空,进程进入睡眠状态。
accept调用成功
函数返回值是一个新的标识符,标识接收的连接
第二个参数描述客户机地址 第三个描述客户机地址长度
*/
//clientfd=accept(sockfd, (struct sockaddr *)&client_addr, &length);//接收连接请求
//clientfd=accept(sockfd, (struct sockaddr *)&client_addr,&length);
cout<<"服务器:准备接收"<<endl;
clientfd = accept(sockfd, (struct sockaddr*)&client_addr, (socklen_t *)&length);
if(clientfd==-1)
{
cout<<"服务器:接收失败"<<endl;
exit(1);
}
pid=fork();
if(pid==0)
{
while (1)
{
bzero(buf, sizeof(buf));
tt=time(NULL);
ttm=localtime(&tt);//获取当前时间参数
strcpy(buf, asctime(ttm));// 将时间拷贝到缓冲区
send(clientfd, buf, strlen(buf), 0);//发送数据
sleep(2);
}
close(clientfd);
}
else if(pid>0)
{
close(clientfd);//父进程关闭套接字 ,准备下一个客户端连接
}
}
return 0;
}
int client()
{
int ret;
char buf[BUF_SIZE];
int sockfd;//套接字描述符
struct sockaddr_in serv_addr;// 服务器端的端口号和ip
sockfd=socket(AF_INET, SOCK_STREAM, 0);
if(sockfd==-1)
{
cout<<" 客户端:socket创建失败"<<endl;
return 2;
}
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(PORT);
//inet_aton(IP, (struct in_addr *)&serv_addr.sin_addr.s_addr);
serv_addr.sin_addr.s_addr=INADDR_ANY;
cout<<"客户端:准备connect"<<endl;
ret=connect(sockfd, (const struct sockaddr *)&serv_addr, sizeof(serv_addr));
cout<<"客户端:connect完成"<<endl;
if(ret==-1)
{
cout<<"客户端:connect失败"<<endl;
return 3;
}
else
{
cout<<"客户端:connect success"<<endl;
}
while (1)
{
bzero(buf, sizeof(buf));
recv(sockfd, buf, sizeof(buf), 0);
printf("客户端:接收到数据:%s",buf);
sleep(1);
}
close(sockfd);
return 0;
}
void *thread_server(void*arg)
{
server();
pthread_exit(NULL);
}
void *thread_client(void*arg)
{
client();
pthread_exit(NULL);
}
int main(int argc, const char * argv[])
{
cout<<"开始"<<endl;
pthread_t thread1,thread2;
int ret;
ret=pthread_create(&thread2, NULL, thread_client, NULL);
if(ret!=0)
{
printf("client创建失败\n");
exit(1);
}
else
{
printf("client创建成功\n");
}
ret=pthread_create(&thread1, NULL, thread_server, NULL);
if(ret!=0)
{
printf("server创建失败\n");
exit(1);
}
else
{
printf("server创建成功\n");
}
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}