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