本篇文章为总结使用C语言的api来完成TCP通信的基本功能,如果您对Socket不了解,请先阅读上一篇理论知识:iOS Socket理论知识!
如果文章中有任何您认为不正确的或者有疑问的,请联系笔者!
TCP Socket编程
TCP是面向连接的,安全可靠的传输层协议。注意:Socket通信一定有要服务端和客户端。
1.1 TCP Socket客户端
客户端的工作流程:首先调用socket函数创建一个Socket,然后指定服务端的IP地址和端口号,就可以调用sendto将字符串传送给服务器端,并可以调用recvfrom接收服务器端返回的字符串,最后关闭该socket。
笔者这里分成了六步:第一步:创建socket并配置socket
第二步:调用bind绑定监听ip和端口号
第三步:调用connect连接服务器
第四步:调用getsockname获取套接字信息
第五步:调用send发送消息到服务器端
第六步:调用close关闭socket
这里没有写接收来自服务器端的消息,大家可以自行添加。
1.1.1 客户端的代码实现:-(void)tcpClient{
//第一步:创建soket
//TCP是基于数据流的,因此参数二使用SOCK_STREAM
interror=-1;
intclientSocketId=socket(AF_INET,SOCK_STREAM,0);
BOOLsuccess=(clientSocketId!=-1);
structsockaddr_inaddr;
//第二步:绑定端口号
if(success){
NSLog(@"clientsocketcreatesuccess");
//初始化
memset(&addr,0,sizeof(addr));
addr.sin_len=sizeof(addr);
//指定协议簇为AF_INET,比如TCP/UDP等
addr.sin_family=AF_INET;
//监听任何ip地址
addr.sin_addr.s_addr=INADDR_ANY;
error=bind(clientSocketId,(conststructsockaddr*)&addr,sizeof(addr));
success=(error==0);
}
if(success){
//p2p
structsockaddr_inpeerAddr;
memset(&peerAddr,0,sizeof(peerAddr));
peerAddr.sin_len=sizeof(peerAddr);
peerAddr.sin_family=AF_INET;
peerAddr.sin_port=htons(1024);
//指定服务端的ip地址,测试时,修改成对应自己服务器的ip
peerAddr.sin_addr.s_addr=inet_addr("192.168.1.107");
socklen_taddrLen;
addrLen=sizeof(peerAddr);
NSLog(@"willbeconnecting");
//第三步:连接服务器
error=connect(clientSocketId,(structsockaddr*)&peerAddr,addrLen);
success=(error==0);
if(success){
//第四步:获取套接字信息
error=getsockname(clientSocketId,(structsockaddr*)&addr,&addrLen);
success=(error==0);
if(success){
NSLog(@"clientconnectsuccess,localaddress:%s,port:%d",
inet_ntoa(addr.sin_addr),
ntohs(addr.sin_port));
//这里只发送10次
intcount=10;
do{
//第五步:发送消息到服务端
send(clientSocketId,"哈哈,server您好!",1024,0);
count--;
//告诉server,客户端退出了
if(count==0){
send(clientSocketId,"exit",1024,0);
}
}while(count>=1);
//第六步:关闭套接字
close(clientSocketId);
}
}else{
NSLog(@"connectfailed");
//第六步:关闭套接字
close(clientSocketId);
}
}
}
1.1.2 客户端的打印日志2015-12-0618:35:00.385iOS-Socket-C-Version-Client[9726:4256295]clientsocketcreatesuccess
2015-12-0618:35:00.386iOS-Socket-C-Version-Client[9726:4256295]willbeconnecting
2015-12-0618:35:00.507iOS-Socket-C-Version-Client[9726:4256295]clientconnectsuccess,localaddress:192.168.1.100,port:50311
说明连接服务器成功,然后发送了消息到服务器端。
1.2 TCP Socket服务器端
服务器端的工作流程:首先调用socket函数创建一个套接字,然后调用bind函数将其与本机地址以及一个本地端口号绑定,接收到一个客户端时,服务器显示该客户端的IP地址,并将字串返回给客户端。
笔者这里分成了五步:第一步:创建socket并配置socket
第二步:调用bind绑定服务器本机ip及端口号
第三步:调用listen监听客户端的连接,并指定同时最多可让accept的数量
第四步:调用accept等待客户端的连接
第五步:调用recvfrom接收来自客户端的消息
第六步:调用close关闭socket
1.2.1 服务器端代码实现-(void)tcpServer{
//第一步:创建socket
interror=-1;
//创建socket套接字
intserverSocketId=socket(AF_INET,SOCK_STREAM,0);
//判断创建socket是否成功
BOOLsuccess=(serverSocketId!=-1);
//第二步:绑定端口号
if(success){
NSLog(@"serversocketcreatesuccess");
//Socketaddress
structsockaddr_inaddr;
//初始化全置为0
memset(&addr,0,sizeof(addr));
//指定socket地址长度
addr.sin_len=sizeof(addr);
//指定网络协议,比如这里使用的是TCP/UDP则指定为AF_INET
addr.sin_family=AF_INET;
//指定端口号
addr.sin_port=htons(1024);
//指定监听的ip,指定为INADDR_ANY时,表示监听所有的ip
addr.sin_addr.s_addr=INADDR_ANY;
//绑定套接字
error=bind(serverSocketId,(conststructsockaddr*)&addr,sizeof(addr));
success=(error==0);
}
//第三步:监听
if(success){
NSLog(@"bindserversocketsuccess");
error=listen(serverSocketId,5);
success=(error==0);
}
if(success){
NSLog(@"listenserversocketsuccess");
while(true){
//p2p
structsockaddr_inpeerAddr;
intpeerSocketId;
socklen_taddrLen=sizeof(peerAddr);
//第四步:等待客户端连接
//服务器端等待从编号为serverSocketId的Socket上接收客户连接请求
peerSocketId=accept(serverSocketId,(structsockaddr*)&peerAddr,&addrLen);
success=(peerSocketId!=-1);
if(success){
NSLog(@"acceptserversocketsuccess,remoteaddress:%s,port:%d",
inet_ntoa(peerAddr.sin_addr),
ntohs(peerAddr.sin_port));
charbuf[1024];
size_tlen=sizeof(buf);
//第五步:接收来自客户端的信息
//当客户端输入exit时才退出
do{
//接收来自客户端的信息
recv(peerSocketId,buf,len,0);
if(strlen(buf)!=0){
NSString*str=[NSStringstringWithCString:bufencoding:NSUTF8StringEncoding];
if(str.length>=1){
NSLog(@"receivedmessagefromclient:%@",str);
}
}
}while(strcmp(buf,"exit")!=0);
NSLog(@"收到exit信号,本次socket通信完毕");
//第六步:关闭socket
close(peerSocketId);
}
}
}
}
1.2.2 服务器端的打印日志2015-12-0618:34:31.258iOS-Socket-C-Version-Server[39929:2622200]serversocketcreatesuccess
2015-12-0618:34:31.258iOS-Socket-C-Version-Server[39929:2622200]bindserversocketsuccess
2015-12-0618:34:31.259iOS-Socket-C-Version-Server[39929:2622200]listenserversocketsuccess
2015-12-0618:35:00.743iOS-Socket-C-Version-Server[39929:2622200]acceptserversocketsuccess,remoteaddress:192.168.1.100,port:50311
2015-12-0618:35:00.743iOS-Socket-C-Version-Server[39929:2622200]receivedmessagefromclient:哈哈,server您好!
2015-12-0618:35:00.743iOS-Socket-C-Version-Server[39929:2622200]receivedmessagefromclient:哈哈,server您好!
2015-12-0618:35:00.743iOS-Socket-C-Version-Server[39929:2622200]receivedmessagefromclient:哈哈,server您好!
2015-12-0618:35:00.744iOS-Socket-C-Version-Server[39929:2622200]receivedmessagefromclient:哈哈,server您好!
2015-12-0618:35:00.744iOS-Socket-C-Version-Server[39929:2622200]receivedmessagefromclient:哈哈,server您好!
2015-12-0618:35:00.744iOS-Socket-C-Version-Server[39929:2622200]receivedmessagefromclient:哈哈,server您好!
2015-12-0618:35:00.744iOS-Socket-C-Version-Server[39929:2622200]receivedmessagefromclient:哈哈,server您好!
2015-12-0618:35:00.744iOS-Socket-C-Version-Server[39929:2622200]receivedmessagefromclient:哈哈,server您好!
2015-12-0618:35:00.744iOS-Socket-C-Version-Server[39929:2622200]receivedmessagefromclient:哈哈,server您好!
2015-12-0618:35:00.745iOS-Socket-C-Version-Server[39929:2622200]receivedmessagefromclient:哈哈,server您好!
2015-12-0618:35:00.745iOS-Socket-C-Version-Server[39929:2622200]receivedmessagefromclient:exit
2015-12-0618:35:00.745iOS-Socket-C-Version-Server[39929:2622200]收到exit信号,本次socket通信完毕
我们这里打印出了客户端发来的消息,由于上面实现的代码中,只发10次,所以这里只有10条。
源代码
注意:这里面有两个工程,一个是客户端,一个是服务器端。运行时,先运行服务器端,然后再选择客户端。另外,客户端所指定的服务器端的ip地址一定要修改成您本机对应的ip,不然使用笔者这里的ip就会失败。
关键词: