代码如下:
服务端
#include <sys/socket.h>//sever #include <sys/types.h> #include <unistd.h> #include <arpa/inet.h> #include <netinet/in.h> #include <errno.h> #include <strings.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <netinet/tcp.h> char host_name[20]; int port = 7777; int main() { struct sockaddr_in sin, pin; int sock_descriptor, temp_sock, address_size; int i, recvlen, on = 1; int nZero = 1; int leftlen = 0, sendlen = 0, retlen = 0; char buf[16384], sendbuf[1024] = {0}, *ptr = NULL; //通过socket(int domain,int type,int protocol)的函数原型创建AF_INIT协议族的流 //类型的socket,当然type除了流socket的之外还有SOCKET_RAW, //据说这种类型的socket甚至可以伪装数据包 sock_descriptor = socket(AF_INET, SOCK_STREAM, 0); setsockopt(sock_descriptor, SOL_SOCKET, SO_REUSEADDR, &nZero, sizeof(int)); setsockopt(sock_descriptor, SOL_SOCKET, SO_REUSEPORT, &nZero, sizeof(int)); setsockopt(sock_descriptor, IPPROTO_TCP, TCP_NODELAY, (char*)&nZero, sizeof(int)); //int keepAlive = 1; //setsockopt(sock_descriptor, SOL_SOCKET, SO_KEEPALIVE,(void *)keepAlive, sizeof(keepAlive)); bzero(&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; //地址结构的端口地址,port是主机字节序,通过htons()进行字节序转换成网络字节序 sin.sin_port = htons(port); //将sin的地址和socket文件描述符绑定到一起,绑定是数据接收和发//送的前提 if (bind(sock_descriptor, (struct sockaddr *)&sin, sizeof(sin)) == -1) { perror("call to bind"); exit(1); } //监听用来初始化服务器可连接队列,因为一次只能处理一个连接请求 //当收到多个请求,将会存储在队列中,先到先得 if (listen(sock_descriptor, 100) == -1) { perror("call to listen"); exit(1); } printf("Accpting connections...\n"); address_size = sizeof(pin); //接收客户机,返回句柄 temp_sock = accept(sock_descriptor, (struct sockaddr *)&pin, &address_size); while (1) { //temp_sock = accept(sock_descriptor,(struct sockaddr *)&pin,&address_size); char buffer[1024] = { 0 }; //句柄分辨不同客户端 printf("temp_sock=%d\n",temp_sock); //链接失败 if (temp_sock == -1) { perror("call to accept"); exit(1); } //int recvlen = recv(temp_sock, buf,sizeof(buf),0); ptr = buffer; //收数据传入buffer int recvlen = recv(temp_sock, ptr, 1024, 0); //断开连接 if (recvlen == -1) { perror("call to recv"); exit(1); } else if (recvlen == 0)//无数据 { printf("断线重连...\n"); temp_sock = accept(sock_descriptor, (struct sockaddr *)&pin, &address_size); continue; } //send(tmp_sock, buffer, 1024, 0); //收到数据,打印 printf("received msg: %s, size:%d\n", buffer, recvlen); //break; //send data retlen = 0; ptr = sendbuf; // printf("sendlen1 = %d\n", sendlen); //while (leftlen) { // printf("sendbuf1:%s\n", sendbuf); printf("sever_input:"); // gets(sendbuf); scanf("%s", &sendbuf); // sprintf(sendbuf, "hello\n"); // printf("sendbuf2:%s\n", sendbuf); // printf("sendlen2 = %d\n", sendlen); sendlen = strlen(sendbuf); // printf("sendlen3 = %d\n", sendlen); //表示已经完成一次发送 if (0 == leftlen) { leftlen = sendlen; printf("leftlen = sendlen;\n"); } //退出标识符 if (0 == strcmp(sendbuf, "quit")) { printf("quit...\n"); break; } //发送 printf("retlen1 = %d\n", retlen); //retlen = send(sock_descriptor, sendbuf, sendlen, 0); retlen = send(temp_sock, sendbuf, sendlen, 0); printf("retlen2 = %d\n", retlen); if (retlen < 0) { printf("retlen < 0\n"); if (errno == EINTR) retlen = 0; else{ printf("exit..."); exit(1); } } else{ printf("retlen3 = %d\n", retlen); } leftlen -= retlen; //} } close(temp_sock); close(sock_descriptor); return 0; }
客户端
#include <stdio.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <syslog.h> #include <errno.h> #include <stdlib.h> #define MAX_LISTEN_NUM 5 #define SEND_BUF_SIZE 100 #define RECV_BUF_SIZE 100 #define SERVER_PORT 7777 char * server_ip = "192.168.60.253"; int main() { int sock_fd = 0; char recvbuf[RECV_BUF_SIZE] = { 0 }; char sendbuf[SEND_BUF_SIZE] = { 0 }; int recvlen = 0; int retlen = 0; int sendlen = 0; int leftlen = 0; char *ptr = NULL; //指向缓冲区的指针 struct sockaddr_in ser_addr; //memset(&ser_addr, 0, sizeof(ser_addr)); bzero(&ser_addr, sizeof(ser_addr)); ser_addr.sin_family = AF_INET; //地址族inet //inet_aton("192.168.60.253", (struct in_addr *)&ser_addr.sin_addr); inet_pton(AF_INET, server_ip, &ser_addr.sin_addr); //将整型变量从主机字节顺序转变成网络字节顺序 ser_addr.sin_port = htons(SERVER_PORT); sock_fd = socket(AF_INET, SOCK_STREAM, 0); if (sock_fd < 0) { perror("connecting to socket\n"); fprintf(stderr, "%s:%d, create socket failed", __FILE__, __LINE__); exit(1); } int nZero = 1;//套接口初始化 setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &nZero, sizeof(int)); setsockopt(sock_fd, SOL_SOCKET, SO_REUSEPORT, &nZero, sizeof(int)); //if(connect(sock_fd, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) < 0) if (connect(sock_fd, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) == -1) { fprintf(stderr, "%s:%d, connect socket failed", __FILE__, __LINE__); exit(1); } // sprintf(sendbuf, "hello server\n"); //send data //sendlen = strlen(sendbuf) +1; retlen = 0; //leftlen = sendlen; ptr = sendbuf; //while(leftlen){ //发送缓存数据 while (1) { //发送缓存数据 printf("input message:"); gets(sendbuf); // //scanf("%s",sendbuf); sendlen = strlen(sendbuf); //说明一条消息已经发送完毕 if (0 == leftlen) { leftlen = sendlen; } //退出条件 if (0 == strcmp(sendbuf, "quit")) { printf("quit...\n"); break; } //printf("retlen:%d,sock_fd:%d,sendlen:%d,leftlen:%d\n", retlen, sock_fd, sendlen, leftlen); //retlen = send(sock_fd, ptr, sendlen, 0); // printf("sendbuf:%s\n",sendbuf); retlen = send(sock_fd, sendbuf, sendlen, 0); //printf("retlen:%d,sock_fd:%d,sendlen:%d,leftlen:%d\n", retlen, sock_fd, sendlen, leftlen); if (retlen < 0) { printf("retlen < 0\n"); if (errno == EINTR) //判断信号是否中断 retlen = 0; else printf("exit..."); exit(1); } leftlen -= retlen; // printf("leftlen=%d\n",leftlen); //ptr += retlen; // printf("retlen:%d,sock_fd:%d,sendlen:%d,leftlen:%d\n",retlen,sock_fd,sendlen,leftlen); //receive data recvlen = 0; //重置 retlen = 0; ptr = recvbuf; //指针ptr->缓冲区函数 leftlen = RECV_BUF_SIZE - 1; //do { retlen = recv(sock_fd, ptr, leftlen, 0); if (retlen < 0) { if (errno == EINTR) retlen = 0; else exit(1); } recvlen += retlen; leftlen -= retlen; ptr += retlen; //} while (recvlen && leftlen); printf("receive data is : %s", recvbuf); // sprintf(sendbuf, "hello server/n"); } //while(1) close(sock_fd); }