今天比较闲,玩一下linux下的TCP编程,下面是具体实现以及对TCP编程的具体总结。
以下是TCP步骤
服务器端 : 客户端:
socket() socket()
bind() connect()
listen() send/recv()/write()/read()
accept() close()
send/recv()/write()/read()
close()
服务端实现:
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<string.h>
int main()
{
//创建一个socket
int listenSocket=socket(AF_INET,SOCK_STREAM,0);
//配置ip port 协议
struct sockaddr_in addrSrc,addrClient;
addrSrc.sin_family=AF_INET;
addrSrc.sin_port=htons(6666);
addrSrc.sin_addr.s_addr=INADDR_ANY;
//绑定
bind(listenSocket,(struct sockaddr*)&addrSrc,sizeof(struct sockaddr_in));
//监听
listen(listenSocket,5);
int connfd=0;
int len=sizeof(struct sockaddr_in);
connfd=accept(listenSocket,(struct sockaddr*)&addrClient,&len);
char *ipStr=inet_ntoa(addrClient.sin_addr);
printf("connect is %s\n",ipStr);
char sendBuf[100]="hello client!";
//发送信息到客户端
send(connfd,sendBuf,strlen(sendBuf)+1,0);
while(1)
{
//接收客户端信息
char recvBuf[100]={0};
int ret=recv(connfd,recvBuf,sizeof(recvBuf)-1,0);
if(0==ret)
{
printf("%s is leave!\n",ipStr);
break;
}
char printBuf[1024]={0};
//字符串拼接
sprintf(printBuf,"from %s: %s",ipStr,recvBuf);
puts(printBuf);
}
//关闭套接字
close(connfd);
close(listenSocket);
return 0;
}
客户端实现:
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<string.h>
int main()
{
//创建一个socket
int clientSocket=socket(AF_INET,SOCK_STREAM,0);
//配置ip port 协议
struct sockaddr_in addrSrc;
memset(&addrSrc,0,sizeof(struct sockaddr_in));
addrSrc.sin_family=AF_INET;
addrSrc.sin_port=htons(6666);
addrSrc.sin_addr.s_addr=inet_addr("127.0.0.1");
connect(clientSocket,(const struct sockaddr *)&addrSrc,sizeof(struct sockaddr_in));
//接受信息
char recvBuf[1024]={0};
recv(clientSocket,recvBuf,sizeof(recvBuf)-1,0);
printf("recv from server is :%s\n",recvBuf);
while(1)
{
//发送信息
char sendBuf[100]={0};
scanf("%s",sendBuf);
send(clientSocket,sendBuf,strlen(sendBuf)+1,0);
}
//关闭套接字
close(clientSocket);
return 0;
}
个人理解与总结:
1、struct sockaddr_in是ipv4地址的结构体,一般1024以内的端口不要使用,因为可能是系统端口。
2、如果TCP通信突然断开连接,然后再次运行程序的时候提示绑定失败,原因是linux限制了同一个端口号的绑定时间间隔。这时候有两种方法可以解决:一是换端口号,如果不是传参的话就得重新编译。二是通过setsockopt()接口来取消端口绑定的限制;以下是实现代码:
int opt = 1;
if (setsockopt(tcpsock, SOL_SOCKET, SO_REUSEADDR, &opt,sizeof(opt)) < 0)
{
perror("setsockopt error");
}
3、TCP通信的特点:面向连接,是可靠的,支持错误重传,不会丢包。
4、TCP通信的过程还会发生三次握手和四次挥手,相对比较繁琐,后面探讨这个过程,暂时总结到这里。