网络编程学习笔记9-第一个netcat的实现(thread-per-connection)
实现简单的netcat,每次读开一个线程,视频p20
本笔记参考的视频链接:https://www.bilibili.com/video/BV1Ht411p7wx?p=20
库链接:https://github.com/chenshuo/muduo
参考链接:https://blog.csdn.net/MonroeD/article/details/71252365
下面的程序是一个简单的netcat的实现
这里是thread-per-connection的实现,针对连接数目不多的情况,每次读开一个线程,负责从stdin写到socket
在服务端和客户端进行编译,我这里是
g++ netcat_thread.cc -o netcat_thread -lpthread
你自己改成对应的名字,而且-lpthread是必须的,因为程序使用了pthread库
编译完成就可以运行了
服务端:
./netcat_thread -l 12345
客户端:
./netcat_thread 192.168.200.134 12345
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <error.h>
#include <strings.h>
#include <sys/types.h>
#include <pthread.h>
#include <fcntl.h>
#include <stdbool.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <linux/tcp.h>
#include <signal.h>
#include <arpa/inet.h>
#define MAX 8192
#define SIZE 10
void* readsock(void *arg)
{
int *sock = (int *)arg;
char buf[MAX];
int nr;
while ( (nr = recv(*sock, buf, sizeof(buf), 0)) > 0)
{
int nw = write(STDOUT_FILENO, buf, nr);
if (nr < nw)
{
break;
}
}
printf("connection closed by peer.\n");
exit(0); //should somehow nofity main thread
}
void readstdin(int sockfd)
{
char buf[MAX];
int nr;
while ( (nr = read(STDIN_FILENO, buf, sizeof(buf))) > 0)
{
int nw = send(sockfd, buf, nr, 0);
if (nw < nr)
{
break;
}
}
}
void run(int sockfd)
{
//read from sock to stdout
pthread_t pid;
pthread_create(&pid, NULL, readsock, (void*)&sockfd);
//read from stdin to sockfd
readstdin(sockfd);
//close, fixme
close(sockfd);
pthread_join(pid,NULL);
}
int main(int argc, char **argv)
{
//sigpipe
signal(SIGPIPE, SIG_IGN);
if (argc < 3)
{
printf("Usage:\n %s hostname port\n %s -l port\n", argv[0], argv[0]);
return 0;
}
int port = atoi(argv[2]);
if (strcmp(argv[1], "-l") == 0)
{
struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
assert(listenfd >= 0);
//address reuse and no nagle
int reuse = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
setsockopt(listenfd, IPPROTO_TCP, TCP_NODELAY, &reuse, sizeof(reuse));
int ret = bind(listenfd, (struct sockaddr*)&address, sizeof(address));
assert(ret >= 0);
ret = listen(listenfd,5);
assert(ret >= 0);
//printf("Listening...\n");
struct sockaddr_in client;
int len = sizeof(client);
int sockfd = accept(listenfd, (struct sockaddr *)(&client), (socklen_t*)&len);
assert(sockfd > 0);
run(sockfd);
}
else
{
int sockfd;
struct sockaddr_in ser;
bzero(&ser,sizeof(ser));
sockfd = socket(AF_INET,SOCK_STREAM,0);
ser.sin_family = AF_INET;
ser.sin_addr.s_addr = inet_addr(argv[1]);
if(argv[2])
{
ser.sin_port = htons(port);
}
ser.sin_port = htons(12345);
connect(sockfd, (struct sockaddr*)&ser, sizeof(ser));
run(sockfd);
}
return 0;
}
最近真的很忙,忙到没空学习了,等过了这一两周一定会赶上进度