服务器客户机聊天程序(非阻塞套接字)
serve.cpp
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main()
{
int sfp, nfp;
struct sockaddr_in s_add, c_add;
socklen_t sin_size;
unsigned short portnum = 10051;
printf("Hello I am a server, Welcome to connect me !\r\n");
sfp = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sfp)
{
printf("socket fail !\r\n");
return -1;
}
printf("socket ok !\r\n");
int on = 1;
setsockopt(sfp, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); //允许地址的立即重用
bzero(&s_add, sizeof(struct sockaddr_in));
s_add.sin_family = AF_INET;
s_add.sin_addr.s_addr = htonl(INADDR_ANY); //绑定本机所有网卡
s_add.sin_port = htons(portnum);
if(-1 == bind(sfp, (struct sockaddr *)(&s_add),sizeof(s_add)))
{
printf("bind fail: %d!\r\n", errno);
return -1;
}
printf("bind ok !\r\n");
if(-1 == listen(sfp, 5))
{
printf("listen fail!\r\n");
return -1;
}
printf("listen ok \r\n");
while(1)
{
sin_size = sizeof(s_add);
nfp = accept(sfp, (struct sockaddr *)(&c_add), &sin_size);
if (-1 == nfp)
{
printf("accept fail !\r\n");
return -1;
}
printf("accept ok!\r\nServer start get coonect from ip=%s, port=%d\r\n", inet_ntoa(c_add.sin_addr), ntohs(c_add.sin_port));
if (-1 == write(nfp, "Hello,client,you are welcome!\r\n", 32))
{
printf("write fail!\r\n");
return -1;
}
printf("write ok!\r\n");
close(nfp);
puts("cotinue to listen(y/n)?");
char ch[2];
scanf("%s", ch); //读两个字符
if (ch[0] != 'y')
{
break;
}
}
printf("bye!\n");
close(sfp);
return 0;
}
client.cpp
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#define BUFFER_SIZE 1023
int setnoblocking(int fd)
{
int old_operation = fcntl(fd, F_GETFL);
int new_operation = old_operation | O_NONBLOCK;
fcntl(fd, F_SETFL, new_operation);
return old_operation;
}
int unblock_connect(const char *ip, int port, int time)
{
int ret = 0;
struct sockaddr_in address;
bzero(&address, sizeof(address));
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_family = AF_INET;
address.sin_port = htons(port);
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
int fdopt = setnoblocking(sockfd);
ret = connect(sockfd, (struct sockaddr *)&address, sizeof(address));
printf("connect ret code =%d\n", ret);
if (ret == 0)
{
printf("connect with srver immediately\n");
fcntl(sockfd, F_SETFL, fdopt); //set old optional back
return sockfd;
}
//unblock mode -->coonect return immediately ! ret = -1 & errno = EINPROGRESS
else if (errno != EINPROGRESS)
{
printf("ret = %d\n", ret);
printf("unblock connect failed\n");
return -1;
}
else if (errno == EINPROGRESS)
{
printf("unblock mode socket is connecting...\n");
}
//use select to check write event ,if the socket is writable ,then connect is complete successfully
fd_set readfds;
fd_set writefds;
struct timeval timeout;
FD_ZERO(&writefds);
FD_SET(sockfd, &writefds);
timeout.tv_sec = time;
timeout.tv_usec = 0;
ret = select(sockfd + 1, NULL, &writefds, NULL, &timeout);
if (ret <= 0)
{
printf("connection time out \n");
close(sockfd);
return -1;
}
if (!FD_ISSET(sockfd, &writefds))
{
printf("no events on sockfd found\n");
close(sockfd);
return -1;
}
int error = 0;
socklen_t length = sizeof(error);
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &length) < 0)
{
printf("get socket option failed\n");
close(sockfd);
return -1;
}
if (error != 0)
{
printf("connection failed after select with the error: %d\n", error);
close(sockfd);
return -1;
}
//connection successful
printf("connection ready after select with the socket :%d\n", sockfd);
fcntl(sockfd, F_SETFL, fdopt); //set oldoptional back
printf("connect ok!\r\n");
int recbytes;
int sin_size;
char buffer[1024] = {0};
if (-1 == (recbytes = read(sockfd, buffer, 1024))) //接受数据
{
printf("read data fail !\r\n");
return -1;
}
printf("read ok:");
buffer[recbytes] = '\0';
printf("%s\r\n", buffer);
return sockfd;
}
int main(int argc, char *argv[])
{
const char ip[] = "192.168.30.138";
int port = 10051;
int sockfd = unblock_connect(ip, port, 1);
if (sockfd < 0)
{
printf("sockfd error! return -1\n");
return 1;
}
close(sockfd);
return 0;
}