基于socket的简单tcp客户端与服务端程序
前一段时间,我实习所在公司的同事说想学习网络编程的知识,我向他介绍了我学习网络编程的历程,在此给大家分享一下,希望能给刚入门的小伙伴带来帮助。我当时学网络编程时,没有志同道合的小伙伴,没有专业的导师教导,自己在这个过程中摸索前行,其中的困难只有自己清楚。
自己的学习历程:
1,window网络编程带我入门,发现自己写的程序竟然可以在网络上通讯,当时感觉很神奇,由此激发我学习网络编程的兴趣。
2,渐渐的发现window网络编程的API满足不了我的需求,然后就转到Linux/Unix网络编程。
3,在实验室所谓的项目组(就我一个人)首次接触到了epoll。
在Linux下学习Linux/Unix网络编程,我的学习过程是按照下面的模式循序渐进的:
- 1个服务端对应1个客户端
1个服务端对应n个客户端
分别使用select,poll,epoll实现1个服务端对应n个客户端。 分析select,poll,epoll三者有何不同?
下面给大家分享一个基于socket的简单tcp客户端与服务端程序,
回头有时间再分享一个http下载服务器程序到github。
makefile
all:
rm -rf server
rm -rf client
gcc -Wall -g server.c -o server
gcc -Wall -g client.c -o client
服务端程序
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <stdlib.h>
#define BUFFSIZE 20480
#define BACKLOG 100
int main(int argc, char **argv)
{
int flag;
int clientfd;
int listenfd = 0;
int reuse = 1;
int addrlen;
char buff[BUFFSIZE];
struct sockaddr_in addr;
struct sockaddr_in cliaddr;
addrlen = sizeof(struct sockaddr_in);
if (argc < 2)
{
printf("Usage: %s ip port\n", argv[0]);
goto end;
}
memset(&addr, 0, addrlen);
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(argv[2]));
addr.sin_addr.s_addr = inet_addr(argv[1]);
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd == -1)
{
printf("fail in socket(), errno : %d, %s\n", errno, strerror(errno));
goto end;
}
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1)
{
printf("fail in setsockopt(), errno : %d, %s\n", errno, strerror(errno));
goto end;
}
if ((bind(listenfd, (const struct sockaddr *)&addr, addrlen)) == -1)
{
printf("fail in bind(), errno : %d, %s\n", errno, strerror(errno));
goto end;
}
if (listen(listenfd, BACKLOG) == -1)
{
printf("fail in listen(), errno : %d, %s\n", errno, strerror(errno));
goto end;
}
while (1)
{
printf("waiting client connect...\n");
memset(&cliaddr, 0, addrlen);
clientfd = accept(listenfd, (struct sockaddr *)&cliaddr, (socklen_t *)&addrlen);
if (clientfd == -1)
{
printf("fail in accept(), errno : %d, %s\n", errno, strerror(errno));
continue;
}
printf("new client from %s:%d\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
while (1)
{
memset(buff, 0, sizeof(buff));
flag = recv(clientfd, buff, BUFFSIZE - 1, 0);
if (flag == 0)
{
printf("peer shutdown\n");
break;
}
else if (flag == -1)
{
if (errno == EAGAIN)
continue;
else
{
printf("fail in recv()\n");
break;
}
}
printf("\nrecv data: %s\n", buff);
if (send(clientfd, buff, strlen(buff) + 1, 0) == -1)
break;
}
close(clientfd);
}
end:
if (listenfd)
close(listenfd);
return 0;
}
客户端程序
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#define MAX_BUFF_SIZE 1024
int main(int argc, char **argv)
{
int flag;
int clientfd;
int reuse = 1;
int addrlen;
char buff[MAX_BUFF_SIZE];
struct sockaddr_in addr;
addrlen = sizeof(struct sockaddr_in);
if (argc < 2)
{
printf("Usage: %s ip port\n", argv[0]);
goto end;
}
memset(&addr, 0, addrlen);
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(argv[2]));
addr.sin_addr.s_addr = inet_addr(argv[1]);
clientfd = socket(AF_INET, SOCK_STREAM, 0);
if (clientfd == -1)
{
printf("fail in socket(), errno : %d, %s\n", errno, strerror(errno));
goto end;
}
if (setsockopt(clientfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1)
{
printf("fail in setsockopt(), errno : %d, %s\n", errno, strerror(errno));
goto end;
}
if (connect(clientfd, (const struct sockaddr *)&addr, addrlen) == -1)
{
printf("fail in connect(), errno : %d, %s\n", errno, strerror(errno));
goto end;
}
while (1)
{
printf("\nplease input data:\n");
memset(&buff, 0, sizeof(buff));
fflush(stdin);
scanf("%s", buff);
printf("send date ...\n");
if (send(clientfd, buff, strlen(buff), 0) == -1)
{
printf("fail in send(), errno : %d, %s\n", errno, strerror(errno));
goto end;
}
printf("reve data ...\n");
memset(buff, 0, sizeof(buff));
flag = recv(clientfd, buff, sizeof(buff) - 1, 0);
if (flag == -1)
{
printf("fail in recv()\n");
goto end;
}
else if (flag == 0)
{
printf("peer shutdown\n");
goto end;
}
else
{
printf("recv data:\n%s\n", buff);
}
}
end:
if (clientfd)
close(clientfd);
return 0;
}