代码如下:
服务端
#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);
}