69,377
社区成员
发帖
与我相关
我的任务
分享
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#define SERV_PORT 8000
#define info(fmt, ...) printf("%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
int
serv(void)
{
int ret;
int servfd, clntfd;
struct sockaddr_in servaddr;
int optval;
ssize_t len;
char buf[1024];
servfd = socket(PF_INET, SOCK_STREAM, 0);
optval = 1;
setsockopt(servfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(servfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
listen(servfd, 5);
clntfd = accept(servfd, NULL, NULL);
for (;;) {
getchar();
memset(buf, 0, sizeof(buf));
len = recv(clntfd, buf, sizeof(buf), 0);
}
}
int
clnt(void)
{
int ret;
int fd;
struct sockaddr_in addr;
fd_set wfds;
struct timeval tv;
int n;
ssize_t len;
char s[] = "0123456789ABCDEF";
fd = socket(PF_INET, SOCK_STREAM, 0);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(SERV_PORT);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
int count = 0;
for (;;) {
FD_ZERO(&wfds);
FD_SET(fd, &wfds);
tv.tv_sec = 10;
tv.tv_usec = 0;
/* 如果这里不进行select, 接收方缓冲区和发送方缓冲区都满的情况下send会阻塞
* 使用select可以判断这种情况, 进行相应的处理(例如超时控制) */
n = select(fd + 1, NULL, &wfds, NULL, &tv);
if (n == 0) {
info("select n=%d: %s\n", n, "timeout");
continue;
}
len = send(fd, s, strlen(s), 0);
count += len;
info("send count=%d\n", (int)count);
}
return 0;
}
int
main(int argc, char *argv[])
{
pid_t pid;
pid = fork();
if (pid == 0) {
(void)serv();
} else {
sleep(1);
(void)clnt();
}
return 0;
}
/******************************************************************************\
* ioctl.c - TCP server
*
* This is a part of the Microsoft Source Code Samples.
* Copyright 1996-1997 Microsoft Corporation.
* All rights reserved.
* This source code is only intended as a supplement to
* Microsoft Development Tools and/or WinHelp documentation.
* See these sources for detailed information regarding the
* Microsoft samples programs.
\******************************************************************************/
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define DEFAULT_PORT 5001
int ReadAndEcho(SOCKET , char *,int ) ;
int WriteMessage(SOCKET , char *,int ) ;
void Usage(char *progname) {
fprintf(stderr,"Usage\n%s -e [endpoint] -i [interface]\n",
progname);
fprintf(stderr,"Where:\n");
fprintf(stderr,"\tendpoint is the port to listen on\n");
fprintf(stderr,"\tinterface is the ipaddr (in dotted decimal notation)");
fprintf(stderr," to bind to\n");
fprintf(stderr,"Defaults are 5001 and INADDR_ANY\n");
WSACleanup();
exit(1);
}
int main(int argc, char **argv) {
char Buffer[128];
char *interface= NULL;
unsigned short port=DEFAULT_PORT;
int fromlen;
int i, ioctl_opt =1;
struct sockaddr_in local, from;
WSADATA wsaData;
SOCKET listen_socket, msgsock;
fd_set readfds, writefds, exceptfds;
/* Parse arguments */
if (argc >1) {
for(i=1;i <argc;i++) {
if ( (argv[i][0] == '-') || (argv[i][0] == '/') ) {
switch(tolower(argv[i][1])) {
case 'i':
interface = argv[++i];
break;
case 'e':
port = atoi(argv[++i]);
break;
default:
Usage(argv[0]);
break;
}
}
else
Usage(argv[0]);
}
}
if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR) {
fprintf(stderr,"WSAStartup failed with error %d\n",WSAGetLastError());
WSACleanup();
return -1;
}
if (port == 0){
Usage(argv[0]);
}
//
// The fd sets should be zeroed out before using them to prevent errors.
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
memset(Buffer,0,sizeof(Buffer));
local.sin_family = AF_INET;
//
// bind to specific interface if desired.
local.sin_addr.s_addr = (!interface)?INADDR_ANY:inet_addr(interface);
/*
* Port MUST be in Network Byte Order
*/
local.sin_port = htons(port);
listen_socket = socket(AF_INET, SOCK_STREAM,0); // TCP socket
if (listen_socket == INVALID_SOCKET){
fprintf(stderr,"socket() failed with error %d\n",WSAGetLastError());
WSACleanup();
return -1;
}
//
// bind() associates a local address and port combination with the
// socket just created.
if (bind(listen_socket,(struct sockaddr*)&local,sizeof(local) )
== SOCKET_ERROR) {
fprintf(stderr,"bind() failed with error %d\n",WSAGetLastError());
WSACleanup();
return -1;
}
//
// start listening on the socket for incoming connections
//
if (listen(listen_socket,5) == SOCKET_ERROR) {
fprintf(stderr,"listen() failed with error %d\n",WSAGetLastError());
WSACleanup();
return -1;
}
printf("%s: Listening on port %d\n",argv[0],port);
//
// Set the socket to non-blocking mode.
//
if (ioctlsocket(listen_socket,FIONBIO,&ioctl_opt) == SOCKET_ERROR) {
fprintf(stderr,"ioctlsocket failed %d\n",WSAGetLastError());
WSACleanup();
return -1;
}
//
// The structure of the loop below is very simple. We only accept one
// connection at a time. As soon as another client connects, we
// disconnect the first one, and start talking to the new client.
// All this server does is to echo the data received on the socket
// back to the client.
//
// This is not a very realistic server, but it does serve to show that
// select() does not scale very well on win32. If we were dealing
// with more than one client, we would have to have a list of sockets
// that are in each fdset to be able to check them when select()
// returns.
//
while(1) {
//
// A socket in the listen() state becomes ready to read when a
// client connects to it. An accept() will complete without
// blocking.
// Since select sets the sockets that are ready to be read from or
// written to, we have to include listen_socket in the fdset each time
// through the loop.
//
FD_SET(listen_socket,&readfds);
i = select(0,&readfds,&writefds,&exceptfds,NULL);
if (i == SOCKET_ERROR) {
fprintf(stderr,"select failed %d\n",WSAGetLastError());
}
if (i==0){
fprintf(stderr,"Select returned no fds ready\n");
}
if (FD_ISSET(listen_socket, &readfds)){
//
// close the previous client socket.
// We must also clear it from the fdset to prevent select()
// from failing.
//
closesocket(msgsock);
FD_CLR(msgsock,&readfds);
FD_CLR(msgsock,&writefds);
fromlen = sizeof(from);
msgsock= accept(listen_socket,(struct sockaddr*)&from,&fromlen);
if (msgsock == INVALID_SOCKET) {
fprintf(stderr,"accept failed %d\n",WSAGetLastError());
WSACleanup();
return -1;
}
FD_SET(msgsock,&writefds);
FD_SET(msgsock,&readfds);
continue;
}
if (FD_ISSET(msgsock,&readfds) ) {
//
// socket is ready to read, i.e., there is data on the socket.
//
if (ReadAndEcho(msgsock,Buffer,sizeof(Buffer))<0) {
fprintf(stderr,"terminating connection\n");
FD_CLR(msgsock,&readfds);
FD_CLR(msgsock,&writefds);
closesocket(msgsock);
continue;
}
}
if (FD_ISSET(msgsock,&writefds) ){
if (WriteMessage(msgsock,Buffer,sizeof(Buffer)) <=0) {
fprintf(stderr,"terminating connection\n");
FD_CLR(msgsock,&readfds);
FD_CLR(msgsock,&writefds);
closesocket(msgsock);
continue;
}
}
FD_SET(msgsock,&writefds);
FD_SET(msgsock,&readfds);
}
}
int ReadAndEcho(SOCKET insock, char *Buffer,int size) {
int rc;
rc = recv(insock,Buffer,size,0);
if (rc == SOCKET_ERROR) {
fprintf(stderr,"recv() failed with error %d\n",WSAGetLastError());
return -1;
}
if (rc ==0) {
fprintf(stderr,"Connection closed by client\n");
return 0;
}
printf("Received [%s] from client\n",Buffer);
return rc;
}
int WriteMessage(SOCKET outsock, char *Buffer,int size) {
int rc;
int lasterr;
printf("Sending [%s] to client\n",Buffer);
rc = send(outsock,Buffer,size, 0);
if (rc == SOCKET_ERROR) {
lasterr = WSAGetLastError();
if (lasterr == WSAEWOULDBLOCK)
return 0;
else {
fprintf(stderr,"send() failed with error %d\n",lasterr);
return -1;
}
}
if (rc ==0) {
fprintf(stderr,"Connection closed by client\n");
}
return rc;
}