#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
// http://www.cnblogs.com/lzjsky/archive/2013/03/18/2965983.html
- (int)setupClient
{
char buff[64] = {0};
int size = 0;
char* addr = "192.168.8.126";
short port = 4567;
// 屏蔽SIGPIPE信号
signal(SIGPIPE, SIG_IGN);
// 建立套接口
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (sock == -1)
return -1;
// 设置地址可重用
int opt = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int)) != 0)
return -1;
// 设置套接口为异步(非阻塞)
int iSave = fcntl(sock, F_GETFL);
fcntl(sock, F_SETFL, iSave | O_NONBLOCK);
// 设置服务器信息
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = inet_addr(addr);
// 由于套接口已经被设置成了异步, 因此connect只是触发一个连接动作并没有等它真正的去连接
if (0 != connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)))
{
// 在异步模式, 这些错误被认为是正确的
if (errno != EISCONN &&
errno != EINPROGRESS &&
errno != EWOULDBLOCK &&
errno != EAGAIN &&
errno != EALREADY)
return -1;
}
// 当套接口可写时, 说明连接完成
{
fd_set fd;
FD_ZERO(&fd);
FD_SET(sock, &fd);
struct timeval timeout0;
timeout0.tv_sec = 3000;
timeout0.tv_usec = 0;
if (select(sock+1, NULL, &fd, NULL, &timeout0) <= 0) // 等待可写, 异常或者超时
return -1;
}
// 发送数据
size = send(sock, buff, sizeof(buff), 0);
if (size < 0)
return -1;
// 当套接口可读时, 说明有数据到达
{
fd_set fd;
FD_ZERO(&fd);
FD_SET(sock, &fd);
struct timeval timeout1;
timeout1.tv_sec = 3;
timeout1.tv_usec = 0;
if (select(sock+1, &fd, NULL, NULL, &timeout1) <= 0) // 等待可读, 异常或者超时
return -1;
}
// 接收数据, 可能send过来了1000数据, 但是本次recv只拿到200. 不能使用MSG_WAITSTREAM, 可能会导致下一次recv出错, MSG_DONTWAIT / MSG_WAITSTREAM
size = recv(sock, buff, sizeof(buff), 0);
if (size < 0)
return -1;
// 关闭套接口
close(sock);
return 0;
}
- (int)setupServer
{
char buff[64] = {0};
int size = 0;
char* addr = "192.168.8.126";
short port = 4567;
// 屏蔽SIGPIPE信号
signal(SIGPIPE, SIG_IGN);
// 建立套接口
int server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (server_socket == -1)
return -1;
// 设置本机信息
struct sockaddr_in server_addr;
server_addr.sin_len = sizeof(struct sockaddr_in);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = inet_addr(addr);
// 绑定套接口: 将创建的socket绑定到本地的IP地址和端口, 此socket是半相关的, 只是负责侦听客户端的连接请求, 并不能用于和客户端通信
int bind_result = bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (bind_result == -1)
return -1;
// listen侦听, 第一个参数是套接字, 第二个参数为等待接受的连接的队列的大小, 在connect请求过来的时候, 完成三次握手后先将连接放到这个队列中, 直到被accept处理. 如果这个队列满了, 且有新的连接的时候, 对方可能会收到出错信息.
if (listen(server_socket, 5) == -1)
return -1;
for (int i = 0; i < 5; i++)
{
// 返回的client_socket为一个全相关的socket, 其中包含client的地址和端口信息, 通过client_socket可以和客户端进行通信.
struct sockaddr_in client_addr;
socklen_t client_addr_len;
int client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_addr_len);
if (client_socket == -1)
return -1;
// 发送数据
size = send(client_socket, buff, sizeof(buff), 0);
if (size < 0)
return -1;
// 接收数据
size = recv(client_socket, buff, sizeof(buff), 0);
if (size < 0)
return -1;
// 关闭套接口
close(client_socket);
}
// 关闭套接口
close(server_socket);
return 0;
}
No.14 Xcode(5.1.x) socket
最新推荐文章于 2021-12-24 12:41:36 发布