[cpp] view plain copy
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#define BUFFER_SIZE 1024
int main(int argc, char** argv)
{
if(argc != 2)
{
printf("Usage:\n%s <port>", argv[0])
return 0
}
struct sockaddr_in myAddr, clientAddr
int socketFd, clientFd
unsigned int clientAddrLen = sizeof(clientAddr)
int receivedLength
char buffer[BUFFER_SIZE]
memset(&clientAddr, 0, sizeof(clientAddr))
memset(&myAddr, 0, sizeof(myAddr))
myAddr.sin_family = AF_INET
myAddr.sin_port = htons(atoi(argv[1]))
myAddr.sin_addr.s_addr = htonl(INADDR_ANY)
socketFd = socket(AF_INET, SOCK_STREAM, 0)
bind(socketFd, (struct sockaddr*)&myAddr, sizeof(myAddr))
listen(socketFd, 5)
clientFd = accept(socketFd, (struct sockaddr *)&clientAddr, &clientAddrLen)
receivedLength = recv(clientFd, buffer, BUFFER_SIZE, 0)
buffer[receivedLength] = '\0'
printf("Received a message from %s:%u:\n%s\n"
, inet_ntoa(clientAddr.sin_addr)
, ntohs(clientAddr.sin_port),buffer)
send(clientFd, buffer, receivedLength, 0)
close(clientFd)
close(socketFd)
return 0
}
假设这个程序的名字是TcpServer,在编译好的可执行文件的目录下,输入:./TcpServer 2333启动服务器程序
然后使用netcat来向它发起来接:nc 127.0.0.1 2333
在netcat里输入一些字符,按回车以后,可以在TcpServer的输出中看到收到的数据,在netcat里可以看到服务器返回的数据。
也可以和《Linux网络编程(1)》里面的程序相互测试一下效果。
服务器程序
/* include udpservselect01 */#include "unp.h"
int
main(int argc, char **argv)
{
int listenfd, connfd, udpfd, nready, maxfdp1
char mesg[MAXLINE]
pid_t childpid
fd_set rset
ssize_t n
socklen_t len
const int on = 1
struct sockaddr_in cliaddr, servaddr
void sig_chld(int)
/* 4create listening TCP socket */
listenfd = Socket(AF_INET, SOCK_STREAM, 0)
bzero(&servaddr, sizeof(servaddr))
servaddr.sin_family = AF_INET
servaddr.sin_addr.s_addr = htonl(INADDR_ANY)
servaddr.sin_port = htons(SERV_PORT)
Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr))
Listen(listenfd, LISTENQ)
/* 4create UDP socket */
udpfd = Socket(AF_INET, SOCK_DGRAM, 0)
bzero(&servaddr, sizeof(servaddr))
servaddr.sin_family = AF_INET
servaddr.sin_addr.s_addr = htonl(INADDR_ANY)
servaddr.sin_port = htons(SERV_PORT)
Bind(udpfd, (SA *) &servaddr, sizeof(servaddr))
/* end udpservselect01 */
/* include udpservselect02 */
Signal(SIGCHLD, sig_chld) /* must call waitpid() */
FD_ZERO(&rset)
maxfdp1 = max(listenfd, udpfd) + 1
for ( ) {
FD_SET(listenfd, &rset)
FD_SET(udpfd, &rset)
if ( (nready = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0) {
if (errno == EINTR)
continue /* back to for() */
else
err_sys("select error")
}
if (FD_ISSET(listenfd, &rset)) {
len = sizeof(cliaddr)
connfd = Accept(listenfd, (SA *) &cliaddr, &len)
if ( (childpid = Fork()) == 0) { /* child process */
Close(listenfd) /* close listening socket */
str_echo(connfd) /* process the request */
exit(0)
}
Close(connfd) /* parent closes connected socket */
}
if (FD_ISSET(udpfd, &rset)) {
len = sizeof(cliaddr)
n = Recvfrom(udpfd, mesg, MAXLINE, 0, (SA *) &cliaddr, &len)
Sendto(udpfd, mesg, n, 0, (SA *) &cliaddr, len)
}
}
}
/* end udpservselect02 */
创建TCP套接字
17~28 创建一个监听套接字并捆绑服务器到总所周知的端口,设置 SO_REUSEADDR套接字选项防止该端口上已有连接存在。
创建UDP套接字
30~38 还创建了一个UDP套接字捆绑于TCP套接字相同的端口,设置 SO_REUSEADDR套接字选项,因为TCP端口是独立于UDP端口的。
给SIGCHLD建立信号处理程序
42 因为TCP连接将由某个子程序处理。给出这个信号处理函数见下面。
准备调用select
44~45 我们给select初始化一个描述符集,并计算出我们等待的两个描述符的较大者。
调用select
47~54 我们调用select只是为了等待监听TCP套接字的可读条件或UDP套接字的可读条件。 既然我们的sig_chld信号处理函数可能中断我们对select的调用,我们于是需要处理EINTR错误。
处理新的客户端连接
56-66 当监听的TCP套接字可读时,我们accept一个新的客户连接,fork一个子程序,并在子程序进程中调用str_echo函数。
处理数据报的到达
68~74 如果UDP套接字可读,那么已有一个数据报到达。我们使用recvfrom读入它,再使用sendto把它发回客户端。
客户端程序(tcp和udp)
#include "unp.h"int
main(int argc, char **argv)
{
int sockfd
struct sockaddr_in servaddr
if (argc != 2)
err_quit("usage: tcpcli <IPaddress>")
sockfd = Socket(AF_INET, SOCK_STREAM, 0)
bzero(&servaddr, sizeof(servaddr))
servaddr.sin_family = AF_INET
servaddr.sin_port = htons(SERV_PORT)
Inet_pton(AF_INET, argv[1], &servaddr.sin_addr)
Connect(sockfd, (SA *) &servaddr, sizeof(servaddr))
str_cli(stdin, sockfd) /* do it all */
exit(0)
}
UDP客户端程序
#include "unp.h"int
main(int argc, char **argv)
{
int sockfd
struct sockaddr_in servaddr
if (argc != 2)
err_quit("usage: udpcli <IPaddress>")
bzero(&servaddr, sizeof(servaddr))
servaddr.sin_family = AF_INET
servaddr.sin_port = htons(SERV_PORT)
Inet_pton(AF_INET, argv[1], &servaddr.sin_addr)
sockfd = Socket(AF_INET, SOCK_DGRAM, 0)
dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr))
exit(0)
}
信号处理程序
#include "unp.h"void
sig_chld(int signo)
{
pid_t pid
int stat
while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0)
printf("child %d terminated\n", pid)
return
}
UDP的回射服务器程序:dg_echo函数
#include <unp.h>void dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen)
{
int n
socklen_t len
char mesg[MAXLINE]
for()
{
len = clilen
n = Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len)
Sendto(sockfd, mesg, n, 0, pcliaddr, len)
}
}
UDP的回射客户程序:dg_cli函数
#include <unp.h>void dg_cli(FILE *fp, int sockfd, const SA* pservaddr, socklen_t servlen)
{
int n
char sendline[MAXLINE], recvline[MAXLINE+1]
while(Fgets(sendline, MAXLINE, fp) != NULL)
{
Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen)
n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL)
recvline[n] = '\0'
Fputs(recvline, stdout)
}
}
简单的写了一下,没有加注释,应该很好理解,满意的话请采纳#include <stdio.h>
#include <sys/socket.h>
#include <pthread.h>
void *thread(void *st)
int main(int argc, char *argv[])
{
pthread_t tid
int ret, fd
struct sockaddr_in info
fd = socket(AF_INET, SOCK_STREAM, 0)
if(fd <0)
goto socket_error
{
int var = 1
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &var, sizeof(var))
}
info.sin_family = AF_INET
info.sin_port = htons(80)
info.sin_addr.s_addr = 0
ret = bind(fd, (void *)&info, sizeof(info))
if(ret)
goto bind_error
ret = listen(fd, 10)
if(ret)
goto listen_error
while(1)
{
clientfd = accept(fd, NULL, NULL)
pthread_create(&tid, NULL, thread, (void *)clientfd)
}
return 0
socket_error:
printf("socket error!\n")
return -1
bind_error:
printf("bind error!\n")
return -2
lister_error:
printf("lister error!\n")
return -2
}
void *thread(void *st)
{
int ret, rd
char buf[BUFSIZE]
int clientfd = (int)st
rd = read(clientfd, buf, sizeof(buf))
if(rd <0)
{
printf("read error!\n")
return
}
write(clientfd, "shou dao!", 9)
close(clientfd)
}
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)