本文共 3295 字,大约阅读时间需要 10 分钟。
//1.创建socket
/*
int socket(int domain, int type, int protocol);
1.协议族 ipv4或者其他的ip协议.
2.type 指定传输层使用TCP或者 UDP (TCP SOCK_STREAM流) (UDP SOCK_DGRAM数据报文)
3.protocol指定传输层使用的协议
返回值 大于0 创建socket成功
*/
int clientSocket =socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
NSLog(@"%d",clientSocket);
//2.建立连接
/*
1.socket
2.const struct sockaddr * 指定对方服务器的ip地址和端口号等信息结构体
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port=htons(PORT);
addr.sin_addr.s_addr = inet_addr(SERVER_IP);
sockaddr_in 比 sockaddr更加容易看的明白,可以类型转换
3.结构体的字节长度
返回值: 0 成功 非0 失败
*/
struct sockaddr_in addr;
//指定协议族 ipv4
addr.sin_family = AF_INET;
//端口号,htons高地位转换
addr.sin_port = htons(12345);
//12345-->0x3039-->0x3930-->14640
// NSLog(@"%d",htons(12345));
//指定IP地址,inet_addr把字符串转换成网络地址(数字)
addr.sin_addr.s_addr =inet_addr("127.0.0.1");
int connResult = connect(clientSocket, (const struct sockaddr *)&addr, sizeof(addr));
//本地开启服务器终端 (netcat) nc -lk 12345
if(connResult == 0){
NSLog(@"ok");
}else{
NSLog(@"fail");
}
//3.发送数据给服务器
/*
1.socket
2.要发送的数据
3.要发送数据的字节长度
4.调用执行方式 flag是否阻塞,一般填0即可
返回值:成功发送的字节数
*/
char * str = "itcast";
ssize_t sentLen = send(clientSocket, str, strlen(str), 0);
//sizeof表示在内存中保存该变量需要多少字节 ,一个字节8位
// NSLog(@"%zd %lu %lu",sentLen,strlen(str),sizeof(str));
//4.接受数据(从服务器接收数据)
/*
1.socket
2.用于保存数据的缓存
3.缓冲区的长度
4.指定调用方式。一般填0即可
返回值接收的字节长度
*/
char *buffer[1024];
ssize_t recvLen = recv(clientSocket, buffer, sizeof(buffer),0);
// NSLog(@"---->%zd",recvLen);
//输出字符串
//二进制 NSData
NSData *data = [NSDatadataWithBytes:buffer length:recvLen];
//字符串输出
NSString *string = [[NSStringalloc] initWithData:dataencoding:NSUTF8StringEncoding];
NSLog(@"%@",string);
//5.关闭数据
//socket
close(clientSocket);
1.close()函数
close 一个套接字的默认行为是把套接字标记为已关闭,然后立即返回到调用进程,该套接字描述符不能再由调用进程使用,也就是说它不能再作为read或write的第一个参数,然而TCP将尝试发送已排队等待发送到对端的任何数据,发送完毕后发生的是正常的TCP连接终止序列。
在多进程并发服务器中,父子进程共享着套接字,套接字描述符引用计数记录着共享着的进程个数,当父进程或某一子进程close掉套接字时,描述符引用计数会相应的减一,当引用计数仍大于零时,这个close调用就不会引发TCP的四路握手断连过程。
2.shutdown()函数
该函数的行为依赖于howto的值
1.SHUT_RD:值为0,关闭连接的读这一半。
2.SHUT_WR:值为1,关闭连接的写这一半。
3.SHUT_RDWR:值为2,连接的读和写都关闭。
终止网络连接的通用方法是调用close函数。但使用shutdown能更好的控制断连过程(使用第二个参数)。
3.两函数的区别 close与shutdown的区别主要表现在: close函数会关闭套接字ID,如果有其他的进程共享着这个套接字,那么它仍然是打开的,这个连接仍然可以用来读和写,并且有时候这是非常重要的 ,特别是对于多进程并发服务器来说。
而shutdown会切断进程共享的套接字的所有连接,不管这个套接字的引用计数是否为零,那些试图读得进程将会接收到EOF标识,那些试图写的进程将会检测到SIGPIPE信号,同时可利用shutdown的第二个参数选择断连的方式。
recvfrom
ssize_t recvfrom(int sockfd,void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen)
windows版本:
int recvfrom(IN SOCKET s, OUT char FAR * buf, IN int len, IN int flags, OUT struct sockaddr FAR * from,IN OUTint FAR * fromlen)
着重强调参数:
sockfd:接收端套接字描述
buf:用于接收数据的应用缓冲区地址
len:指名缓冲区大小
flags:通常为0
src_addr:数据来源端的地址
addrlen:src_addr地址的长度
注意后两个参数是输出参数,其中addrlen既是输入又是输出参数,即值-结果参数,需要在调用时,指明src_addr的长度。另外,如果不关心数据发送端的地址,可以将后两者均设置为NULL。
转载地址:http://cglgi.baihongyu.com/